2012北京航空航天大学考研机试真题

来源:互联网 发布:淘宝客api调用实例php 编辑:程序博客网 时间:2024/04/30 07:00
//下面三个本人的代码都没有经过很严密的测试,可能有bug,望参考时注意</span>  

1.【问题描述】

某些整数能分解成若干个连续整数的和的形式,例如15 = 1 + 2+3+4+5 15 = 4 + 5 + 615 = 7 + 8某些整数不能分解为连续整数的和,例如:16输入:一个整数N(N <= 10000)输出:整数N对应的所有分解组合,按照每个分解中的最小整数从小到大输出,每个分解占一行,每个数字之间有一个空格(每行最后保留一个空格);如果没有任何分解组合,则输出NONE。
/**这题可以采用暴力的解法*注意开始最多是n / 2*/</span>#include <cstdio>int d[200];int main(){int n, size, t, i, j, sum;bool yes;while(~scanf("%d", &n)){yes = false;t = n / 2;for(i = 1; i <= t; i++){sum = 0;j = i;size = 0;while(sum < n){d[++size] = j;sum += j++;}if(sum == n){for(j = 1; j <= size; j++)printf("%d ", d[j]);puts("");yes = true;}}if(!yes)puts("NONE");}return 0;}

2.【问题描述】
小岛面积
1 1 0 0 0 1
1 1 0 1 1 1
0 1 0 1 0 0
1 1 1 1 1 1
上面矩阵的中的1代表海岸线,0代表小岛。求小岛面积(即被1中包围的0的个数)。注意:仅求这样的0,该0所在行中被两个1包围,该0所在列中被两个1包围。
输入:
第一行输入一个整数N,表示输入方阵的维数
输入一个N维方阵
输出:
小岛面积
样例输入:

1 1 1 1 1 1
1 1 0 0 0 1
1 0 0 0 1 0 
1 1 0 1 1 1 
0 1 0 1 0 0 
1 1 1 1 1 1
5
1 1 1 1 0
0 0 1 0 1
1 1 1 0 1
1 0 1 1 1
0 1 1 0 1
5
1 1 1 1 0
0 0 1 0 1
1 0 1 0 1
1 0 1 1 1
0 1 1 0 1
5
1 1 1 1 0
1 0 1 0 1
1 0 1 0 1
1 0 1 1 1
0 1 1 0 1
样例输出:
8
3
2

5

/**这个题目是比较简单的,可以使用广搜来搜索,*因为不满足题目的0只能出现在与边界相连的区域内*所以可以从四个边上的0开始进行搜索,如果0是有路的话,*那边界的0能够达到的0都是不满足题目要求的,*不断标记就行了*代码没有提交过,可能有瑕疵  */#include <cstdio>#include <queue>using namespace std;int a[31][31];int n;bool mar[31][31];int pos[4][2] = {{0, 1},{1, 0},{-1 , 0},{0, -1}};//坐标的四个方向struct E{int a, b;void set(int x, int y){a = x;b = y;}}; queue<E> Q;void init(E &e, int a, int b){e.set(a, b);Q.push(e);};void bfs(){E e, t;int a, b;while(!Q.empty()){e = Q.front();mar[e.a][e.b] = true;Q.pop();for(int i = 0; i < 4; i++){a = e.a + pos[i][0];b = e.b + pos[i][1];if(a < 1 || a > n || b < 1 || b > n)continue;else if(!mar[a][b])init(t, a, b);}}};int main(){int i, j, sum;freopen("in.txt", "r", stdin);//从文件in.txt读入while(~scanf("%d", &n)){sum = 0;for(i = 1; i <= n; i++)for(j = 1; j <= n; j++){scanf("%d", &a[i][j]);mar[i][j] = a[i][j];//一上来把所有的1标记}for(i = 1; i <= n; i++){E e;if(!mar[1][i]){//第一行init(e, 1, i);bfs();}if(!mar[i][1]){//第一列init(e, i, 1);bfs();}if(!mar[n][i]){//最后一行init(e, n, i);bfs();}if(!mar[i][n]){//最后一列init(e, i, n);bfs();}}for(i = 1; i <= n; i++){for(int j = 1; j <= n; j++){if(!mar[i][j])sum++;//数一数最后还有多少组没有标记}}printf("%d\n", sum);}return 0;}


//方法2,采用回溯法


/**采用回溯的方式进行搜索,仍然是从四条边开始,*每到一个顶点,先把这个顶点标记,*然后分别对它的四个相邻的坐标进行同样搜索*术语可能不是很准确*/#include <cstdio>int a[31][31];int n;bool mar[31][31];int pos[4][2] = {{0, 1},{1, 0},{-1 , 0},{0, -1}};//坐标的四个方向void bfs(int a, int b){mar[a][b] = true;//每把一个没有标记的坐标进行搜索,首先把它标记,这个就避免了无限递归for(int i = 0; i < 4; i++){//如果坐标超出范围,跳过这个坐标if(a + pos[i][0] < 1 || a + pos[i][0] > n || b + pos[i][1] < 1 || b + pos[i][1] > n);else if(!mar[a + pos[i][0]][b + pos[i][1]])bfs(a + pos[i][0], b + pos[i][1]);}}int main(){int i, j, sum;freopen("in.txt", "r", stdin);//从文件in.txt读入while(~scanf("%d", &n)){sum = 0;for(i = 1; i <= n; i++)for(j = 1; j <= n; j++){scanf("%d", &a[i][j]);mar[i][j] = a[i][j];//一上来把所有的1标记}for(i = 1; i <= n; i++){if(!mar[1][i]){//第一行bfs(1, i);}if(!mar[i][1]){//第一列bfs(i, 1);}if(!mar[n][i]){//最后一行bfs(n, i);}if(!mar[i][n]){//最后一列bfs(i, n);}}for(i = 1; i <= n; i++){for(int j = 1; j <= n; j++){if(!mar[i][j])sum++;//数一数最后还有多少组没有标记}}printf("%d\n", sum);}return 0;}

3.【问题描述】
统计关键字出现位置
输入:
一行标准c语言代码(字符个数小于300),统计出该字符串中关键字的if,while,for所在的位置,按照关键字出现的顺序依次输出。注意双引号内的不需要统计。
输入:一行标准c语言代码,字符个数小于300
输出:
关键字if,while,for对应的位置,按照关键字出现的顺序依次输出。输出格式为:关键字,后跟冒号,然后是出现的位置。扫描到关键字就输出,每个输出占一行。
样例输入:
#include <stdio.h> int main() {int i = 0; if(i == 0) printf("YES"); return 0;}
#include <stdio.h> int main() {int ifwhile = 0; int forif = 1;char if_for_while = 
'a';char *str = "while"; while(ifwhile == 0) {ifwhile = 1;forif = 0;} if(forif == 0) 
{if_for_while = 'b';} if(ifwhile == 1) {if_for_while = 'c';} return 0;}r_while = 'c';} 
return 0;}
样例输出:
if:43
while:88
if:133
if:170
解题思路:
首先把输入字符串切分为一个个的单词,然后对每个单词进行匹配。注意c语言中的strtok函数,不能够返回位置(当分隔符连续时,比如+=,计算出前导的分割符有几个),所以不能满足本题的要求,必须自己写获取单词的函数(反正也不复杂啦)。因为考虑到引号的问题,我们的解决方案是首先对输入字符串进行预处理,将“”内的每个字符都替换为#,然后再进行单词分割(切词),最后进行匹配。具体步骤:
Ø 输入源码字符串预处理,将””内的每个字符替换为#
Ø 一次获取源码中的单词,看是否为查找的关键词,如果是则输出

#include <stdio.h>#include <ctype.h>#include <string.h>int main(){char s[301];//保存整个字符串char a[100];//保存单词int st, size;//freopen("in.txt", "r", stdin);while(gets(s)){int len = strlen(s);for(int i = 0; i < len; ){printf("i = %d\n", len);size = 0;//如果不是字母的话,判断是不是双引号,要是双引号那就匹配到下一个双引号if(!isalpha(s[i])){if(s[i] == '"')while(s[i++] != '"');elsei++;}//如果是字母"i",那就取一个单词,最后跟if比较,如果是if,那就看看if前是不是空格或者分号,后面是不是空格或者左括号//因为整个程序是一行,所以这样取巧是可以的,while同样的道理else if(s[i] == 'i'){st = i;do{a[size++] = s[i++];}while(isalpha(s[i]));a[size] = 0;if(!strcmp(a, "if") && (s[i] == '(' || s[i] == ' ') && (s[st - 1] == ' '))printf("if:%d\n", st + 1);}else if(s[i] == 'w'){st = i;do{a[size++] = s[i++];}while(isalpha(s[i]));a[size] = 0;if(!strcmp(a, "while") && (s[i] == '(' || s[i] == ' ') && (s[st - 1] == ' ' || s[st - 1] == ';' || s[st - 1] == '}'))printf("while:%d\n", st + 1);}elsei++;}}return 0;}