POJ 1194 Zipper 【dp】【北大ACM/ICPC竞赛训练】

现在做dp题有点感觉了,以前估计会觉得这题很难,现在觉得这是道不是很水的水题

dp[i][j]代表A里前i个加上B里前j个能不能组成C的前i+j个。

至于怎么想到的呢,n是200,有1000组数据,所以猜测要dp二维,然后很容易就想到了。

这里再考虑到C[i+j]的这个元素肯定是由A[i]或B[j]组成(即A的最末尾或B的最末尾,因为要保证原来的order)

所以这就变成了dp[i][j] = dp[i-1][j] | dp[i][j-1]  (当然这是A[i]=B[j]=C[i+j])的情况。

接着想递归怎么写,每次要看正上方和左边的数值,所以从上到下从左到右就可以。边界条件是i=0或j=0的时候

===2018.9.7===

字符串dp的技巧性就是看最后一位,枚举这个字符是怎么得来的

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 int dp[205][205];//dp[i][j]
 6 char a[205],b[205],c[410];
 7 int cnt;
 8 //string a1,b1,c1;
 9 
10 int main(){
11     int t; cin>>t;
12     while(t--){
13         memset(dp,0,sizeof(dp));
14         cin>>a+1>>b+1>>c+1;//范围从1到strlen(a+1> 
15         
16         for(int i=0;i<=strlen(b+1);i++){
17             bool same=true;
18             for(int j=0;j<=i;j++){
19                 if(b[j]!=c[j]) { same=false; break; }
20             }
21             if(same) dp[0][i]=1;
22             else dp[0][i]=0;
23         }
24         
25         for(int i=0;i<=strlen(a+1);i++){
26             bool same=true;
27             for(int j=0;j<=i;j++){
28                 if(a[j]!=c[j]) { same=false; break; }
29             }
30             if(same) dp[i][0]=1;
31             else dp[i][0]=0;
32         }
33         
34     
35         for(int i=1;i<=strlen(a+1);i++){
36             for(int j=1;j<=strlen(b+1);j++){
37                 if( a[i]==c[i+j] ) dp[i][j]|=dp[i-1][j];
38                 if( b[j]==c[i+j] ) dp[i][j]|=dp[i][j-1];
39             }
40         }
41         string ans;
42         if(dp[strlen(a+1)][strlen(b+1)]) ans="yes";
43         else ans="no";
44         
45         cout<<"Data set "<<(++cnt)<<": "<<ans<<endl;
46         
47     }
48 
49     return 0;    
50 }
原文地址:https://www.cnblogs.com/ZhenghangHu/p/9393470.html