算法实验二。
问题 A: 最长公共子序列
题目描述
给你一个序列X和另一个序列Z,当Z中的所有元素都在X中存在,并且在X中的下标顺序是严格递增的,那么就把Z叫做X的子序列。
例如:Z=是序列X=的一个子序列,Z中的元素在X中的下标序列为<1,2,4,6>。
现给你两个序列X和Y,请问它们的最长公共子序列的长度是多少?1,2,4,6>
输入
输入包含多组测试数据。每组输入占一行,为两个字符串,由若干个空格分隔。每个字符串的长度不超过100。
输出
对于每组输入,输出两个字符串的最长公共子序列的长度。
样例输入
abcfbc abfcab
programming contest
abcd mnp
样例输出
4
2
0
提示
代码
#include<bits/stdc++.h>
using namespace std;
/*void LCSlength(int m,int n,char *x,char *y,int c[105][105],int b[105][105])
{
int i,j;
for(i=1;i<=m;i++)
c[i][0]=0;
for(i=1;i<=n;i++)
c[0][i]=0;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(x[i]==y[i])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=2;
}
else
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
}
*/
int main()
{
char x[105],y[105];
int c[105][105];
while(cin>>x+1)
{
cin>>y+1;
int m=strlen(x+1);
int n=strlen(y+1);
for(int i=0;i<=m;i++)
c[0][i]=0;
for(int i=0;i<=n;i++)
c[i][0]=0;
/*for(int i=0;i<=105;i++)
{
for(int j=0;j<=105;j++)
{
c[i][j]=0;
b[i][j]=0;
}
}*/
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(x[i]==y[j])
c[i][j]=c[i-1][j-1]+1;
else
c[i][j]=max(c[i-1][j],c[i][j-1]);
}
}
//cout<<x+1<<y+1<<endl;
//cout<<m<<n<<endl;
cout<<c[m][n]<<endl;
}
return 0;
}
问题 B: 矩阵连乘
题目描述
给定n个矩阵{A1,A2,…,An},及m个矩阵连乘的表达式,判断每个矩阵连乘表达式是否满足矩阵乘法法则,如果满足,则计算矩阵的最小连乘次数,如果不满足输出“MengMengDa“。
输入
输入数据由多组数据组成(不超过10组样例)。每组数据格式如下:
第一行是2个整数n (1≤n≤26)和m(1≤m≤3),表示矩阵的个数。
接下来n行,每行有一个大写字母,表示矩阵的名字,后面有两个整数r和c,分别表示该矩阵的行数和列数,其中1<r, c<100。
第n+1行到第n+m行,每行是一个矩阵连乘的表达式(2<=矩阵个数<=100)。
输出
对于每个矩阵连乘表达式,如果运算不满足矩阵乘法法则的情况(即左矩阵列数与右矩阵的行数不同),则输出“MengMengDa”,否则输出最小矩阵连乘次数。
数据保证结果不超过1e9。
样例输入
3 2
A 10 100
B 5 50
C 100 5
ACB
ABC
样例输出
7500
MengMengDa
提示
代码
#include<iostream>
#include<string.h>
using namespace std;
int m[105][105]={0};
int p[200];
int maxchain(int n)
{
for(int i=1;i<=n;i++)
{
m[i][i]=0;
}
for(int r=2;r<=n;r++)
{
for(int i=1;i<=n-r+1;i++)
{
int j=i+r-1;
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
for(int k=i+1;k<j;k++)
{
int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(t<m[i][j])
{
m[i][j]=t;
}
}
}
}
return m[1][n];
}
int main()
{
int n,m;
while(cin>>n>>m)
{
char chain[30];
int h[30];
int l[30];
for(int i=0;i<n;i++)
{
cin>>chain[i]>>h[i]>>l[i];
}
char test[3][105];
for(int i=0;i<m;i++)
{
cin>>test[i];
}
int key;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(test[i][0]==chain[j])
{
key=j;
break;
}
}
p[0]=h[key];
p[1]=l[key];
int len=strlen(test[i]);
int flag=1;
for(int k=1;k<len;k++)
{
for(int j=0;j<n;j++)
{
if(test[i][k]==chain[j])
{
key=j;
break;
}
}
if(p[k]==h[key])
{
p[k+1]=l[key];
}
else
{
cout<<"MengMengDa"<<endl;
flag=0;
break;
}
}
if(flag==1)
{
cout<<maxchain(len)<<endl;
}
}
}
}
问题 C: 01背包问题
题目描述
已知有N种物品和一个可容纳C重量的背包。每种物品i的重量为Wi,价值为Pi。那么,采用怎样的装包方法才会使装入背包物品的总价值最大。
输入
包含多组测试数据。第一行为一个整数T(1<=T<=10),代表测试数据个数。
接下来有T组测试数据。每组测试数据第一行为背包的重量C(C<10000)和物品个数N(N<1000)。接下来的N行分别为物品的重量cost(1<=cost<=100)和价值val(1<=val<=3000000)。(注意:结果可能超过int范围)
输出
对每组测试数据,输出其对应的所装物品的最大价值。
样例输入
1
10 5
2 6
2 3
6 5
5 4
4 6
样例输出
15
提示
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long w[10010],v[10010],dp[10010];
int t,m,n;
cin>>t;
while(t--)
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
for(int j=m;j>=w[i];j--)
{
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
for(int i=m;i>=2;i--)
{
if(dp[i]!=dp[i-1])
{
cout<<dp[i]<<endl;
break;
}
}
}
return 0;
}
问题 D: 最大子段和
题目描述
给定n个整数组成的序列a1,a2,…an, 求子段和ai+ai+1+…+aj(子段可为空集)的最大值。
输入
包含多组测试数据。第一行为一个整数T(1<=T<=20),代表测试数据个数。
每组测试数据第一行为一个整数n,代表有n个整数(1<=n<=10000)。
接下来一行有n个数x(-1000<=x<=1000)。
输出
输出其对应的最大子段和。
样例输入
1
6
2 -11 4 13 -1 2
样例输出
18
提示
子段可为空集,答案为0
代码
#include<bits/stdc++.h>
using namespace std;
int a[10010];
int sum=0;
int maxsum(int n)
{
int b=0;
for(int i=0;i<n;i++)
{
if(b>0)
{
b+=a[i];
}
else
{
b=a[i];
}
if(b>sum)
{
sum=b;
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int k;
cin>>k;
for(int i=0;i<k;i++)
{
cin>>a[i];
}
maxsum(k);
cout<<sum<<endl;
}
return 0;
}
问题 E: 汽水瓶【25】
题目描述
有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水。小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?
输入
输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1≤n≤100),表示小张手上的空汽水瓶数。n=0表示输入结束,你的程序不应当处理这一行。
输出
对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出 0
样例输入
3
10
81
0
样例输出
1
5
40
提示
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main(){
int n,sum=0;
while(cin>>n&&n!=0){
sum=0;
while(n>2){
sum+=n/3;
n=(n%3)+(n/3);
}
if(n==2) sum++;
cout<<sum<<endl;
}
}