2007-2017年华科软院复试上机题C++版本(上篇)

写在前面的话:
2019年华中科技大学软件学院的复试已经尘埃落定,为了机试也刷了一下历年的软院上机题,虽然并没有用到(2019年软院专硕没有上机),为了造福学弟学妹们,把自己写的代码放出来,仅供参考。
注:使用的c/c++编写的,由于篇幅较长,分为上篇和下篇,上篇为2017年——2013年真题,下篇为2012年——2007年真题加我自己拓展的一些跟历年真题类似的题目,代码中都含题目描述,其中2018年跟2019年软院没有机试,文末也放了pdf的链接供下载
祝都能考上自己心仪的学校!

2017-1-最长公共子串

/*==============================================
求 2 个字符串的最长公共子串,字符串长度不超过 255。
例如:
输入:
What is your name?
My name is pipihui.
输出:
最长公共子串为”name”。
分析:最长公共子串问题,用动态规划,确定 dp[i][j]
i = 0 | j = 0 时,dp[i][j] = 0
str1[i] == str2[j]时,dp[i][j] = dp[i-1][j-1] + 1
str1[i] != str2[j]时,dp[i][j] = 0
注意:1.空格的问题,前面照常写程序,最后输出的时候简化为只输出不为空格的数
2.最长公共子串可能有多个,用endStr1[N]记录dp[i][j]==maxLen的串的end位置,最后循环输出每个子串
by shinerise 2019/2/27
===============================================*/
#include <iostream>
#include <cstdio>
#define N 256
using namespace std;

//用于打印的函数
void printSubstring(char str[], int end, int len){
     int start = end - len + 1;
     for(int i=start; i<=end; i++){
          if(str[i]!=' ')
              cout<<str[i];
     }
     cout<<endl;
}

int main(){
     char str1[N],str2[N];
     int dp[N][N] = {0},maxLen = 0;
     gets(str1);
     gets(str2);
     //计算dp[i][j]的值和maxLen
     for(int i=0;str1[i]!='\0';i++){
          for(int j=0;str2[j]!='\0';j++){
              if(str1[i]==str2[j]){
                   if(i>0&&j>0){
                        dp[i][j]=dp[i-1][j-1]+1;
                   }else{
                        dp[i][j]=1;
                   }
                   if(maxLen<dp[i][j]){
                        maxLen = dp[i][j];
                   }
              }
          }
     }

     int endStr1[N];
     int numMaxLen = 0;

     //记录多个字符串长度为maxLen的end地址
     for(int i=0;str1[i]!='\0';i++){
          for(int j=0;str2[j]!='\0';j++){
              if(dp[i][j] == maxLen){
                   endStr1[numMaxLen++] = i;
              }
          }
     }

     //循环输出每个最长公共子串
     for(int i=0;i<numMaxLen;i++){
          printSubstring(str1, endStr1[i], maxLen);
     }

     getchar();
     return 0;
}

2017-2-国际象棋马走日

/*=====================================
假设国际象棋棋盘有 5*5 共 25 个格子。设计一个程序,使棋子从初始位置(棋盘编号
为 1 的位)开始跳马,能够把棋盘的格子全部都走一遍,每个格子只允许走一次。
(1)输出一个如图 2 的解,左上角为第一步起点。
(2)总共有多少解
回溯法
当确定一个位置之后,要考虑8种可以跳马的方向,
设置一个记步数的变量tag,当tag为25时退出递归,
同时把最后确定的一个位置,即写着25的格子的变量重置为0,同时退回到第24步,
去寻找其它第25步的可能位置。
by shinerise 2019/2/28
========================================*/
#include <iostream>
using namespace std;
int dir[8][2] = {{-1, -2},{-1, 2},{1, 2},{1, -2},{-2, -1},{-2, 1},{2, -1},{2, 1}};
int chess[5][5] = {0};
int sum = 0;//sum表示共有多少种解法

//用于打印的函数
void print(){
	for(int i=0;i<5;i++){
		for(int j=0;j<5;j++){
			cout<<chess[i][j]<<" ";
		}
		cout<<endl;
	}
}

//回溯法遍历各个位置
void visit(int x, int y, int tag){
	if(x>=0&&x<5&&y>=0&&y<5&&chess[x][y]==0){
		chess[x][y] = tag;//若满足条件,标记该点的解
		if(tag==25){
			sum++;
			if(sum==1){
				print();
			}
		}else{
			for(int i=0;i<8;i++){
				visit(x+dir[i][0], y+dir[i][1], tag+1);
			}
		}
		//回溯前清理工作
		chess[x][y] = 0;
	}
}
int main(){
	visit(0, 0, 1);
	cout<<"共有"<<sum<<"种解法";
	return 0;
}

2016-1-青蛙跳台阶

#include <iostream>
#include <string>
using namespace std;
/*===================================
超级青蛙跳台阶。一个台阶总共有 n 级,超级青蛙有能力一次跳到 n 阶台阶,
也可以一次跳 n-1 阶台阶,也可以跳 n-2 阶台阶……也可以跳 1 阶台阶。
问超级青蛙跳到 n 层台阶有多少种跳法?(n<=50)
例:输入台阶数:3
输出种类数:4
解释:4 种跳法分别是(1,1,1),(1,2),(2,1),(3)
分析:f(n) = f(n-1) + f(n-2) + ... + f(2) + f(1) + f(0)
从0级台阶一次跳上n级台阶:f(0) = 1
从1级台阶一次跳上n级台阶:f(1) = f(0)
f(2) = f(1) + f(0)
...
by shinerise 2019/2/28
======================================*/

//n阶台阶的方法个数函数
int getCount(int n){
     int count = 0;//count代表跳台阶的方法个数
     if(n==0){
          return 1;
     }else{
          for(int i=0;i<n;i++){
              count += getCount(i);
          }
          return count;
     }
}

int main(){
     int n;
     cin>>n;
     if(n <= 0){
          cout<<"请输入正确的n级台阶(n为正整数)";
          return -1;
     }else{
          cout<<getCount(n)<<endl;
     }
     return 0;
}

2016-1-拓展-青蛙跳台阶一次只能跳1阶或2阶

#include <iostream>
using namespace std;
/*==============================
一个台阶总共有n级,如果一次可以跳1级或者2级,问一共有多少种跳法
转化成斐波那契数列,n级台阶若第一次跳一级,,后面有f(n-1)次跳法
若第一次跳两级,后面有f(n-2)种跳法
f(n) = f(n-1) + f(n-2)
f(1) = 1
f(2) = 2
by shinerise 2019/2/25
=================================*/

//n级台阶跳法函数
int getCount(int n){
     if(n == 1){
          return 1;
     }else if(n == 2){
          return 2;
     }else{
          return getCount(n-1) + getCount(n-2);
     }
}
int main(){
     int n;
     cin>>n;
     if(n <= 0){
          cout<<"请输入正确的台阶数n(n为正整数)"<<endl;
          return -1;
     }
     cout<<getCount(n)<<endl;
     return 0;
}

2016-2-青蛙杯棒球比赛

#include <iostream>
#include <string>
using namespace std;
/*====================================
青蛙(frog)杯第一届棒球比赛开赛啦。
你现在是一名记分员,输入一个字符串数组(比赛记录情况),按如下规则计分:
1. 如果该字符串是数字:代表当轮比赛的得分情况。
2. 如果该字符串是“+”: 代表当轮比赛得分情况为上两轮之和。
3. 如果该字符串是“C”: 代表上一轮得分无效。
4. 如果该字符串是“D”: 代表当轮比赛得分为上一轮得分的两倍。
你需要得出最后总的得分情况并返回结果。
例:
输入:52CD+
输出:30
解释:
第 1 轮得分 5 分,当前总共得分 5 分。
第 2 轮得分 2 分,当前总共得分 5+2=7 分。
第 3 轮取消上轮得分,当前总共得分 5 分。
第 4 轮获得上一轮双倍得分,当前总共得分 5+10=15 分。
第 5 轮获得上两轮得分之和,当前总共得分 15+5+10=30 分。
分析:栈的用法
by shinerise 2019/2/26
================================*/
int main(){
     string s;
     cin>>s;
     int len = s.length();
     //new[]和delete[]对应使用
     int *stack = new int[len];
     int top = -1;
     //先将数据存储到栈中
     for(int i=0;i<len;i++){
          if(s[i]>='0'&&s[i]<='9'){
              stack[++top] = s[i] - '0';
          }else if(s[i] == '+'){
              if(top < 1){
                   cout<<"非法"<<endl;
                   return -1;
              }
              int a = stack[top-1] + stack[top]; //c为该轮得分
              stack[++top] = a;
          }else if(s[i] == 'C'){
              if(top < 0){
                   cout<<"非法"<<endl;
                   return -1;
              }
              top--;
          }else if(s[i] == 'D'){
              int a = stack[top] * 2;
              stack[++top] = a;
          }else{
              cout<<"非法"<<endl;
              return -1;
          }
     }

     //计算总得分
     int sum = 0;
     for(int i=0;i<=top;i++){
          sum += stack[i];
     }
     cout<<"总得分为"<<sum<<endl;
     return 0;
}

2015-1-最长数字串

#include <iostream>
#include <string>
using namespace std;
/*===============================
1.设计一个程序,输入一个字符串以#结尾,输出此字符串中连续出现最长的数字串以及其
开始的下标,
例:
输入:
ab125ff1234567#
输出:
1234567 开始位置为 8
by shinerise 2019/2/26
================================*/
int main(){
     string s;
     cin>>s;
     char *scpy = new char[s.length()];//scpy用于存储连续数字串的长度
     //将连续数字串长度存储到scpy中
     for(int i=0;s[i]!='#';i++){
          if(s[i]>='0'&&s[i]<='9'){
              if(i != 0){
                   scpy[i] = scpy[i-1] + 1;
              }else{
                   scpy[i] = 0;
              }
          }else{
              scpy[i] = 0;
          }
     }

     int maxLen = 0, end;//end表示最长数字串结束的下标
     //求最长数字串
     for(int i=0;s[i] != '#';i++){
          if(maxLen < scpy[i]){
              maxLen = scpy[i];
              end = i;
          }
     }

     //输出最长数字串以及其开始的下标
     cout<<"最长数字串为";
     for(int i=end-maxLen + 1;i<=end;i++){
          cout<<s[i];
     }
     cout<<endl;
     cout<<"开始的下标为"<<end-maxLen+2<<endl;
     return 0;
}

2015-2-国际象棋马走日(与2017-2相同)

2014-1-完全平方数

#include <iostream>
using namespace std;
/*==================================
在三位整数(100 至 999)中寻找符合下列条件的整数并依次从小到大输出。
(1)完全平方数。
(2)含有两位数字相同。
例:144,676…
by shinerise 2019/2/26
===================================*/
int main(){
     for(int i=10;i<32;i++){
          int j = i * i;//j为100-999之间的完全平方数
          int a, b, c;//a,b,c分别为j的个位、十位、百位
          a = j % 10;
          b = j / 10 % 10;
          c = j / 100;
          if((a==b&&a!=c&&b!=c)||(a!=b&&b==c&&a!=c)||(a!=b&&a==c&&b!=c)){
              cout<<j<<endl;
          }
     }
     system("pause");
     return 0;
}

2014-2-下标为奇数的小写字母转化为大写字母

#include <iostream>
#include <string>
using namespace std;
/*===================================
输入一串字符串,把下标为奇数的小写字母(从 0 开始编号)转换为大写字母。
输出转换后的字符串。
by shinerise 2019/2/26
======================================*/
int main(){
     string s;
     cin>>s;
     for(int i=0;i<s.length();i++){
          if(i%2==1){
              if(s[i]>='a'&&s[i]<='z'){
                   s[i] = 'A'-'a'+s[i];
              }
          cout<<s[i];
          }
     }
     return 0;
}

2013-1-平方回文数

/*=====================================
输出 100-1000 的所有平方回文数。
平分回文数字是满足下列条件的整数:
(1)从左读与从右读都是一样的。
(2)为某一个数的平方。
by shinerise 2019/2/26
======================================*/
#include <iostream>
using namespace std;
int main(){
     int n, a, b, c;//n为所求的三位数,a, b, c分别为三位数的个位,十位,百位
     for(int i=10;i<32;i++){
          n = i * i;
          a = n % 10;
          b = n / 10 % 10;
          c = n / 100;
          if(a == c){
              cout<<n<<endl;
          }
     }
     return 0;
}

2013-2-八皇后

/*============================================
编程解决“八皇后问题”:即在一个 8*8 的矩形格子中排放 8 个皇后,要满足的条件包
括:任意两个皇后不能在同一行,同一列,也不能在同一条对角线上。
要求编程给出解的个数
by shinerise 2019/2/28
=============================================*/
#include <iostream>
using namespace std;
const int N = 9;
int a[50], b[50], c[50];//a表示行,b表示"\", c表示"/",0为可放入,1为不可放入
int chess[N][N] = {0};//chess表示皇后放入的位置,1为皇后,0为空
int sum = 0;//sum表示解个数

//用于打印皇后位置
void print(){
     sum++;
     cout<<"第"<<sum<<"种解法为:"<<endl;
     for(int i=1;i<N;i++){
          for(int j=1;j<N;j++){
              cout<<chess[i][j]<<" ";
          }
          cout<<endl;
     }
}

//回溯法,column为按列搜索能填入的位置
void search(int column){
     //搜索第column列的第row行
     for(int row=1;row<N;row++){
          //皇后满足的条件
          if((a[row]==0)&&(b[row+column]==0)&&(c[column+7-row]==0)){
              //可以放入皇后,放入后将每一行,每一对角线置为1
              chess[row][column] = 1;
              a[row] = 1;
              b[row+column] = 1;
              c[column+7-row] = 1;
              if(column == 8){
                   print();
              }else
                   search(column+1);
              //回溯前清理
              chess[row][column] = 0;
              a[row] = 0;
              b[row+column] = 0;
              c[column+7-row] = 0;
          }
     }
}

int main(){
     search(1);
     cout<<"共有"<<sum<<"种解法"<<endl;
     system("pause");
     return 0;
}

猜你喜欢

转载自blog.csdn.net/Shine_rise/article/details/88615095