1. 题目描述:
N阶楼梯上楼问题:一次可以走两阶或一阶,问有多少种上楼方式。(要求采用非递归)
输入:
输入包括一个整数N,(1<=N<90)。
输出:
可能有多组测试数据,对于每组数据,
输出当楼梯阶数是N时的上楼方式个数。
样例输入:
4
样例输出:
5
分析:假设 f(n) 为上 n 阶楼梯的方法数量。则如果只有 1 阶楼梯,显然只有一种方法走完;如果有 2 阶楼梯,显然有两种走法走完,所以有 f(0)=0, f(1)=1, f(2)=2。当有 n 阶楼梯时,显然每一步只有两种走法(走一阶或走两阶),第一步的走法也不例外。如果第一步走一阶,那还剩下 n-1 阶,则剩下的楼梯共有 f(n-1) 种走法;如果第一步走两阶,则剩下的楼梯共有 f(n-2) 种走法。从而有:对于 n 阶楼梯,共有 f(n-1) + f(n-2)种走法。从而可以得到推导公式:
f(0)=0, f(1)=1, f(2)=2, ..., f(n)=f(n-1) + f(n-2)
很明显,这就是我们非常熟悉的 fibonacci 数列,相信无论是其递归程序还是递推程序,大家都很熟悉吧。
参考答案
#include<stdio.h> void initialize(long int value[], int size)//初始化f(n)的值,避免重复计算 { int k; value[0] = 0; value[1] = 1; value[2] = 2; for(k=3; k<size; k++) { value[k] = value[k-1] + value[k-2]; } } int main() { int n; long int value[91]; initialize(value, 91); while(scanf("%d", &n) != EOF){ printf("%ld\n", value[n]);//直接利用已计算过的f(n)的值 } return 0; }
2. 题目描述:
输入一个ip地址串,判断是否合法。
输入:
输入的第一行包括一个整数n(1<=n<=500),代表下面会出现的IP地址的个数。
接下来的n行每行有一个IP地址,IP地址的形式为a.b.c.d,其中a、b、c、d都是整数。
输出:
可能有多组测试数据,对于每组数据,如果IP地址合法则输出"Yes!”,否则输出"No!”。
样例输入:
2
255.255.255.255
512.12.2.3
样例输出:
Yes!
No!
提示:
合法的IP地址为:
a、b、c、d都是0-255的整数。
参考答案
#include<stdio.h> int main() { int n,a,b,c,d; while(scanf("%d",&n)!=EOF) { while(n--) { scanf("%d.%d.%d.%d",&a,&b,&c,&d); if(a>=0 && a<=255 && b>=0 && b<=255 && c>=0 && c<=255 && d>=0 && d<=255) { printf("Yes!\n"); } else { printf("No!\n"); } } } return 0; }
这种解答会被服务器端判断为正确,但是其实此程序有很多bug(如输入不慎会造成死循环等),所以千万是不能用在实际开发当中的。下面让我们再看一下另一个非常严谨的判断程序,此程序在我机器上运行没有问题,但是此程序提交服务器后被判断为错误答案。
#include<stdio.h> #include<string.h> int main() { char str[501][20]; int str_len, i, dotnum, flag, sum, n, cur; int temp; while(scanf("%d", &n) != EOF) { for(i=0; i<n; i++) { scanf("%s", str[i]); } for(cur=0; cur<n; cur++) { str_len = strlen(str[cur]); flag = 1; //如果输入的IP长度小于7或大于15,则肯定是错误的 if(str_len<7 || str_len>15) { flag=0; } for(i=0, dotnum=0; i<str_len && flag; i++) { sum =0; while(str[cur][i] != '.' && str[cur][i] != '\0') { //如果当前字符不是 0 到 9 中的整数,则肯定不是合法IP temp = str[cur][i] - '0'; if(temp<0 || temp>9) { flag = 0; break; } sum =sum*10 + (str[cur][i++] - '0'); } if(sum>255) { flag = 0; break; } dotnum++; } if(flag && 4==dotnum) { printf("Yes\n"); } else { printf("No\n"); } } } return 0; }
3. 题目描述:
输入一个四行五列的矩阵,找出每列最大的两个数。
输入:
输入第一行包括一个整数n(1<=n<=1000),接下来的四行每行包括五个整数。代表一个四行五列的矩阵,矩阵元素全部是整数。
输出:
可能有多组测试数据,对于每组数据,按照样例输出的格式将每列最大的两个数输出,如果最大的两个数中的一个数在这一列中有多个相同的值,则行值取行值小的那一个。
输出时要保留原矩阵的行列顺序,即在原矩阵中行值小的,在输出矩阵中的行值依然小。
样例输入:
1
1 2 4 9 8
-1 4 9 8 8
12 9 8 7 0
7 8 9 7 0
样例输出:
12 9 9 9 8
7 8 9 8 8
提示:
每个数字后面都要输出一个空格
参考答案
#include<stdio.h> #include<string.h> #include <limits.h> int main() { int n, i, k, in_1, in_2; int num[4][5], result[2][5]; int max_1 = INT_MIN, max_2 = INT_MIN; while(scanf("%d", &n) != EOF) { while(n--) { //接收输入数据 for(i=0; i<4; i++) { for(k=0; k<5; k++) { scanf("%d", &num[i][k]); } } //将结果写入result数组中 for(k=0; k<5; k++) { in_1 = -1; in_2 = -1; max_1 = INT_MIN; max_2 = INT_MIN; /////////////////////////////////////////////// //找出最大数 for(i=0; i<4; i++) { if(num[i][k] > max_1) { in_1 = i; max_1 = num[i][k]; } } //找出次大数 for(i=0; i<4; i++) { //in_1 != i是为了跳过已求得的最大数 if(num[i][k] > max_2 && in_1 != i) { in_2 = i; max_2 = num[i][k]; } } //////////////////////////////////////////////////////////////// //保留原矩阵的行顺序 if(in_1 > in_2) { in_1 = in_1 + in_2; in_2 = in_1 - in_2; in_1 = in_1 - in_2; } result[0][k] = num[in_1][k]; result[1][k] = num[in_2][k]; } //输出结果 for(i=0; i<2; i++) { for(k=0; k<5; k++) { printf("%d ", result[i][k]); } printf("\n"); } } } return 0; }