hdu1501 Zipper[简单DP]
题目地址
题干
代码和解释
最优子结构分析:设这三个字符串分别为a、b、c,如果a、b可以组成c,那么c的最后一个字母必定来自a或者b的最后一个字母。c去除最后一位,就变成由a-1和b或者a和b-1构成c-1的问题。
状态转移方程:DP[i][j]表示c中i个字符来自于a,j个字符来自于b,即由a的前i个字符和b的前j个字符组成c的前i+j个字符。DP[i][j]为1则真,为0则假。
/*给3个字符串,让你判断能不能组合前两个字符串来获得第3个字符串。前两个字符串可以被任意混合,但都必须保持原来的顺序。*/
/*输入:第一行输入一个1到1000的整数,表示样例的数量。一组样例一行。
字符串都只包含大小写字母,第3个字符串的长度必须等于前两个字符串长度之和,前两个字符串长度从1到200*/
/*输出:
Data set n: yes或Data set n: no,每组样例有一个输出。*/
#include<stdio.h>
#include<string.h>
int main()
{
int T;
char a[210];
char b[210];
char c[410];
int len1,len2;
int DP[210][210];//DP[i][j]指c中有i位来自a,j位来自b
int i,j;
int count = 1;
scanf("%d",&T);
while(T--){
scanf("%s%s%s",a+1,b+1,c+1);
len1=strlen(a+1);
len2=strlen(b+1);
memset(DP,0,sizeof(DP));
for(i=1;i<=len1;i++){
if(a[i]==c[i]){
DP[i][0]=1;
}
}
for(j=1;j<=len2;j++){
if(b[j]==c[j]){
DP[0][j]=1;
}
}
for(i=1;i<=len1;i++){
for(j=1;j<=len2;j++){
if((DP[i-1][j]&&a[i]==c[i+j])||(DP[i][j-1]&&b[j]==c[i+j])){
DP[i][j]=1;
}
}
}
if(DP[len1][len2]==1){
printf("Data set %d: yes\n",count);
}
else printf("Data set %d: no\n",count);
count++;
}
return 0;
}
这里的字符串输入是scanf("%s",a+1);而不是scanf("%s",a);我认为是为了方便理解第几位就是第几位,而且方便对DP[i][0]和DP[0][j]的处理。
注意几个字符串数组都要开的大一点,一开始我wa就是因为数组开成201,不够大。
参考
STAY. you have NO WHERE TO GO. try to live it well. for you have only ONE life.