问题 B: 弟弟的作业 时间限制: 1 Sec 内存限制: 128 MB 提交: 80 解决: 41 外部导入 提交状态讨论版 题目描述 你的弟弟刚做完了“100以内数的加减法”这部分的作业,请你帮他检查一下。每道题目(包括弟弟的答案)的格式为a+b=c或者a-b=c,其中a和b是作业中给出的,均为不超过100的非负整数;c是弟弟算出的答案,可能是不超过200的非负整数,也可能是单个字符"?",表示他不会算。 输入 输入文件包含不超过100行,以文件结束符结尾。每行包含一道题目,格式保证符合上述规定,且不包含任何空白字符。输入的所有整数均不含前导0。 输出 输出仅一行,包含一个非负整数,即弟弟答对的题目数量。 样例输入 Copy 1+2=3 3-1=5 6+7=? 99-0=99 样例输出 Copy 2
int main() { char s[30]; int a,b,c; int sum=0; while(scanf("%s",&s)!=EOF) { if(sscanf(s,"%d+%d=%d",&a,&b,&c)==3&&(a+b==c)) sum++; if(sscanf(s,"%d-%d=%d",&a,&b,&c)==3&&(a-b==c)) sum++; } cout<<sum<<endl; return 0; }
其实这个题目就只要判断“=”后面的数整部正确并且是不是“?”;如果是“?”的话就不管,不是的话再判断是不是正确的数,如果是正确的是,那么sum++;
另一种思路就是用atof()函数,在逆波兰表达式中提到过这个函数的一丢丢用法;
以文件结尾结束就是 crl+z会输出sum的答案
问题 C: 求解n阶螺旋矩阵问题 时间限制: 1 Sec 内存限制: 128 MB 提交: 0 解决: 0 201501010119 提交状态讨论版 题目描述 创建n阶螺旋矩阵并输出。 输入 输入包含多个测试用例,每个测试用例为一行,包含一个正整数n(1<=n<=50),以输入0表示结束。 输出 每个测试用例输出n行,每行包括n个整数,整数之间用一个空格分割。 样例输入 Copy 4 0 样例输出 Copy 1 2 3 4 12 13 14 5 11 16 15 6 10 9 8 7
int a[55][55]; int main() { int n,i,j,b; while(scanf("%d",&n)&&n) { int flag=1; for(b=0;b<=(n+1)/2;b++) { for(j=b;j<=n-b-1;j++) a[b][j]=flag++; for(i=b+1;i<n-b-1;i++) a[i][n-b-1]=flag++; for(j=n-b-1;j>b;j--) a[n-b-1][j]=flag++; for(i=n-b-1;i>b;i--) a[i][b]=flag++; } for(i=0;i<n;i++) { for(j=0;j<n;j++) if(j==0) cout<<a[i][j]; else cout<<" "<<a[i][j]; cout<<endl; } } return 0; }
问题 D: 最大子段和 时间限制: 1 Sec 内存限制: 128 MB 提交: 1 解决: 1 201501010119 提交状态讨论版 题目描述 给定n个整数(可能是负数)组成的序列a[1], a[2], a[3], …, a[n],求该序列的子段和如a[i]+a[i+1]+…+a[j]的最大值。 输入 每组输入包括两行,第一行为序列长度n,第二行为序列。 输出 输出字段和的最大值。 样例输入 Copy 5 -1 0 1 2 3 样例输出 Copy 6
int a[1000]; int n; int maxx(int a[],int n) { int b,sum; if(a[0]>0) b=a[0]; //判断第一个数是否为正,为正直接加,为负将b赋值为0; else b=0; sum=b; //sum用来找b中的最大值(也就是找子段和中最大的子段和) for(int i=1;i<n;i++) { if(b>0) //如果b为正,就一直加(不管a[i]是否为负,只要b为正,都要一直加a[i]) b=b+a[i]; else //直到b为负,那么就不管这个子段了,重新从a[i]开始算另一个子段和 b=a[i]; if(b>sum) //取众多子段的最大的那个子段 sum=b; } return sum; } int main() { while(cin>>n) { int i; for(i=0;i<n;i++) cin>>a[i]; cout<<maxx(a,n)<<endl; } return 0; }
动态规划法;
b[i]表示以a[i]结尾的子段和;
判断b[i-1]是否为正,为正的话:b[i-1]+a[i]放在b[i]里;否则,就从下一个子段开始,并且判断每次加的子段的最大值,输出的是最大值sum。
问题 F: 牛牛的字符串 时间限制: 1 Sec 内存限制: 128 MB 提交: 1 解决: 1 201501010119 提交状态讨论版 题目描述 牛牛有两个字符串(可能包含空格),他想找出其中最长的公共连续子串的长度,希望你能帮助他。例如:两个字符串分别为"abede"和"abgde",结果为2。 输入 每组数据包括两行,每行为一个字符串。 输出 输出最长的公共连续子串的长度。 样例输入 Copy abede abgde 样例输出 Copy 2
int dp[1000][1000]; char a[1000],b[1000]; int maxx=0; int lsc(int x,int y) { int i,j; for(i=0;i<x;i++) { if(a[i]==b[0]) dp[i][0]=1; } for(j=0;j<y;j++) { if(b[j]==a[0]) dp[0][j]=1; } for(i=1;i<x;i++) for(j=1;j<y;j++) { if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; if(dp[i][j]>=maxx) maxx=dp[i][j]; } return maxx; } int main() { while(cin>>a) { cin>>b; int x=strlen(a); int y=strlen(b); cout<<lsc(x,y)<<endl;; } return 0; }
这个代码还是有点问题的,因为当输入的两个字符串某个长度为1的时候会输出0,所以我们在主函数中判断一下字符串长度是否为1,为1的话就直接线性查找;
最长公共子序列:要求相对位置一致就行;
dp[i][j]表示x从第一个到第i个,y从第一个到第j个;
填表法:长的为行,短的为列,第一行第二行全0,若行列的两个字母相同,dp数组=左上角的dp数组+1,不相等的话取上面和前面的最大值;
最后取右下角
问题 G: 最长公共子序列问题(LCS)-构造LCS 时间限制: 1 Sec 内存限制: 128 MB 提交: 2 解决: 1 201501010119 提交状态讨论版 题目描述 使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。 输入 每组输入包括两行,每行包括一个字符串。 输出 两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性) 样例输入 Copy acdbxx ccdxx 样例输出 Copy cdxx
char a[1000],b[1000]; int aa[100][100]; int dp[100][100]; void lcs(int i,int j) { if(i==0||j==0) //找完了,结束递归 return ; if(dp[i][j]==1) //先回溯,再输出 { lcs(i-1,j-1); cout<<a[i-1]; } else if(dp[i][j]==2) lcs(i-1,j); else lcs(i,j-1); } int main() { memset(aa,0,sizeof(aa)); while(cin>>a) { cin>>b; int m=strlen(a); int n=strlen(b); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) { if(a[i-1]==b[j-1]) { aa[i][j]=aa[i-1][j-1]+1; dp[i][j]=1; } else { if(aa[i-1][j]>aa[i][j-1]) { aa[i][j]=aa[i-1][j]; dp[i][j]=2; } else { aa[i][j]=aa[i][j-1]; dp[i][j]=3; } } } lcs(m,n); } return 0; }
这是最简单的情况,只要求构造一条最长子序列;
dp数组用来记录存进aa的值是来自上面还是前面还是左对角;
最后递归输出;
问题 H: Max Sum 时间限制: 1 Sec 内存限制: 33 MB 提交: 0 解决: 0 201501010119 提交状态讨论版 题目描述 给你一个序列 a[1],a[2],a[3]......a[n], 你要做的是求出最大字段和. 比如, 输入 6,-1,5,4,-7, 这个序列的最大字段和就是 6 + (-1) + 5 + 4 = 14. 输入 The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000). 输出 每组测试用例输出两行。 第一行是"Case #:" # 表示测试用例的序数。 第二行包括三个数字,最大子段和,以及子段的起始位置和结束位置 例如:输入数组(6,-1,5,4,-7),输出14, 1, 4,其中14表示最大子段和,1表示和最大的子段从第1个数字开始,4表示和最大的子段到第4个数字结束,即(6, -1 , 5, 4)。 样例输入 Copy 2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5 样例输出 Copy Case 1: 14 1 4 Case 2: 7 1 6
int a[1000]; int i,n; int be,ed,k,b,sum; int flag; void maxx(int a[],int n) { for(i=0;i<n;i++) { b=b+a[i]; if(b>sum) { sum=b; ed=i+1; be=k+1; } if(b<0) { b=0; k=i+1; } } return ; } int main() { int t; cin>>t; flag=0; while(t--) { cin>>n; for(i=0;i<n;i++) cin>>a[i]; be=0,ed=0,k=0,b=0,sum=-1; maxx(a,n); flag++; cout<<"Case "<<flag<<":"<<endl<<sum<<" "<<be<<" "<<ed<<endl; } return 0;