目录
问题 A: 习题7-18 日期计算
题目描述
写一个函数,给定年、月、日,计算该日期是该年的第几天。在主函数中输入一个日期(含年、月、日),通过函数调用,得到该日期所对应这一年的第几天,并输出该数值。
输入
三个以空格分隔的整数,分别表示该日期的年、月、日。
输出
输入日期所对应这一年的第几天,一个整数,单独占一行。
样例输入 Copy
2014 3 8
样例输出 Copy
67
提示
可以采用如下函数原型
int getDays(int year, int month, int day);
计算过程中注意闰年。
#include<cmath>
#include<iostream>
using namespace std;
int getDays(int y, int m, int d){
int flag;
if(y%4==0&&y%100!=0||y%400==0)
flag=1;
else
flag=0;
int sum=0;
--m;
switch(m)
{
case 11:
sum+=30;
case 10:
sum+=31;
case 9:
sum+=30;
case 8:
sum+=31;
case 7:
sum+=31;
case 6:
sum+=30;
case 5:
sum+=31;
case 4:
sum+=30;
case 3:
sum+=31;
case 2:
sum=sum+28+flag;
case 1:
sum+=31;
break;
}
sum+=d;
return sum;
}
int main()
{
int y,m,d;
while(cin>>y>>m>>d){
int sum=getDays(y,m,d);
cout<<sum<<endl;
}
return 0;
}
问题 B: 弟弟的作业
题目描述
你的弟弟刚做完了“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
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b;
char d,c;
int flag=0;
char s[4];
int k=0;
while(cin>>a>>c>>b>>d>>s){
if(s[0]=='?')
continue;
else{
for(int i=0;i<strlen(s);i++){
k+=(int)(s[i]-'0')*pow(10,strlen(s)-i-1);
}
if(c=='-'&&a-b==k){
flag++;
}
if(c=='+'&&a+b==k){
flag++;
}
}
k=0;
}
cout<<flag<<endl;
return 0;
}
问题 C: 求解n阶螺旋矩阵问题
题目描述
创建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
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
while(cin>>n&&n){
int a[n][n];
int i,j;
memset(a,0,sizeof(a));
int k=0;
k=a[0][0]=1;
int x,y;
x=0;
y=0;
while(k<n*n){
while(y+1<n&&!a[x][y+1])
a[x][++y]=++k;
while(x+1<n&&!a[x+1][y])
a[++x][y]=++k;
while(y-1>=0&&!a[x][y-1])
a[x][--y]=++k;
while(x-1>=0&&!a[x-1][y])
a[--x][y]=++k;
}
for(i=0;i<n;++i){
for(j=0;j<n;++j){
cout<<a[i][j];
if(j==n-1)
cout<<endl;
else
cout<<" ";
}
}
}
return 0;
}
问题 D: 最大子段和
题目描述
给定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
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int n;
while(cin>>n){
int i;
int a[n];
for(i=0;i<n;i++){
cin>>a[i];
}
int dp[n];
dp[0]=a[0];
for(i=1;i<n;i++){
dp[i]=dp[i-1]<0?a[i]:dp[i-1]+a[i];
}
sort(dp,dp+n);
cout<<dp[n-1]<<endl;
}
return 0;
}
问题 E: 矩阵连乘问题-求最优值
题目描述
使用动态规划算法求解矩阵连乘问题,输出最少乘法次数。
输入
每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。
输出
矩阵连乘最优计算次数。
样例输入 Copy
7 30 35 15 5 10 20 25
样例输出 Copy
15125
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[105][105];
void matrixChain(int a[],int n){
for(int i=1;i<n;i++)
dp[i][i]=0;
for(int r=2;r<n;r++){
for(int i=1;i<n-r+1;i++){
int j=i+r-1;
dp[i][j]=dp[i+1][j]+a[i-1]*a[i]*a[j]+dp[i][i];
for(int k=i+1;k<j;k++){
int t=dp[i][k]+dp[k+1][j]+a[i-1]*a[k]*a[j];
if(t<dp[i][j])
dp[i][j]=t;
}
//cout<<dp[i][j]<<"*"<<i<<"*"<<j<<" ";
}
//cout<<endl;
}
}
int main()
{
int n,m;
while(cin>>m){
int a[m];
int i;
memset(dp,0,sizeof(dp));
for(i=0;i<m;i++){
cin>>a[i];
}
matrixChain(a,m);
cout<<dp[1][m-1]<<endl;
}
return 0;
}
问题 F: 牛牛的字符串
题目描述
牛牛有两个字符串(可能包含空格),他想找出其中最长的公共连续子串的长度,希望你能帮助他。例如:两个字符串分别为"abede"和"abgde",结果为2。
输入
每组数据包括两行,每行为一个字符串。
输出
输出最长的公共连续子串的长度。
样例输入 Copy
abede abgde
样例输出 Copy
2
#include<bits/stdc++.h>
using namespace std;
int main()
{
string a,b;
while(getline(cin,a)){
getline(cin,b);
int la,lb;
la=a.length();
lb=b.length();
int dp[la+1][lb+1];
int i,j;
int M=0;
for(i=0;i<la;i++){
for(j=0;j<lb;j++){
if(a[i]==b[j]){
if(i==0||j==0)
dp[i][j]=1;
else
dp[i][j]=dp[i-1][j-1]+1;
}
else
dp[i][j]=0;
if(dp[i][j]>M)
M=dp[i][j];
}
}
cout<<M<<endl;
M=0;
}
return 0;
}
问题 G: 最长公共子序列问题(LCS)-构造LCS
题目描述
使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性)
样例输入 Copy
acdbxx ccdxx
样例输出 Copy
cdxx
#include<bits/stdc++.h>
using namespace std;
int d[105][105];
void lcs(int i,int j,string a){
if(i==0||j==0)
return ;
if(d[i][j]==1){
lcs(i-1,j-1,a);
cout<<a[i-1];
}else if(d[i][j]==2){
lcs(i-1,j,a);
}else{
lcs(i,j-1,a);
}
}
int main()
{
string a,b;
while(getline(cin,a)){
getline(cin,b);
int la,lb;
la=a.length();
lb=b.length();
int dp[la+1][lb+1];
int i,j;
for(i=0;i<=la;i++)
dp[i][0]=0;
for(i=0;i<=lb;i++)
dp[0][i]=0;
for(i=1;i<=la;i++){
for(j=1;j<=lb;j++){
if(a[i-1]==b[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
d[i][j]=1;
}
else if(dp[i-1][j]>=dp[i][j-1]){
dp[i][j]=dp[i-1][j];
d[i][j]=2;
}
else{
dp[i][j]=dp[i][j-1];
d[i][j]=3;
}
}
}
//cout<<dp[la][lb];
lcs(la,lb,a);
cout<<endl;
}
return 0;
}
问题 H: Max Sum
题目描述
给你一个序列 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
//求出最大子段和以及这一段的起始位置和终点位置
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int n,m;
while(cin>>m){
for(int j=1;j<=m;j++){
cin>>n;
int i;
int a[n];
for(i=0;i<n;i++){
cin>>a[i];
}
int dp[n];
dp[0]=a[0];
int f1,f2;
f1=f2=0;
int M=a[0];
for(i=1;i<n;i++){
dp[i]=dp[i-1]<0?a[i]:dp[i-1]+a[i];
if(M<dp[i])
{
M=dp[i];
f1=i;
}
}
cout<<"Case "<<j<<":"<<"\n"<<M<<" ";
for(i=f1;i>=0;--i){
M-=a[i];
if(M==0){
f2=i;
}
}
++f2;
++f1;
cout<<f2<<" "<<f1<<endl;
}
}
return 0;
}