hdu1501 Zipper[简单DP]

题目地址

hdu1501

题干

代码和解释

最优子结构分析:设这三个字符串分别为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,不够大。

参考

hdu1501最优子结构
hdu1501简单DP

posted @ 2019-07-14 16:19  平静的雨田  阅读(249)  评论(2编辑  收藏  举报