HDU 1501 Zipper

问前两个字符串是否能组合成第三个字符串,保持原字符串的顺序。

看到别人的代码有两种做法:

 

1、DFS

hash数组标记足迹,可以减少重复搜索的次数。

这个代码太过巧妙,体会体会再体会。。

 1 //#define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 bool hash[205][205];
 8 char s1[205], s2[205], s3[410];
 9 
10 bool DFS(int a, int b, int c)
11 {
12     if(s3[c] == '\0')
13         return true;
14     if(hash[a][b])
15         return false;
16     hash[a][b] = true;
17     if(s1[a] == s3[c] && DFS(a+1, b, c+1))
18         return true;
19     if(s2[b] == s3[c] && DFS(a, b+1, c+1))
20         return true;
21     return false;
22 }
23 
24 int main(void)
25 {
26     #ifdef LOCAL
27         freopen("1501in.txt", "r", stdin);
28     #endif
29 
30     int T, kase;
31     scanf("%d", &T);
32     for(kase = 1; kase <= T; ++kase)
33     {
34         printf("Data set %d: ", kase);
35         cin >> s1 >> s2 >> s3;
36         memset(hash, false, sizeof(hash));
37         if(DFS(0, 0, 0))
38             printf("yes\n");
39         else
40             printf("no\n");
41 
42     }
43     return 0;
44 }
代码君

 

2、DP

最优子结构分析:如上例,如果A、B可以组成C,那么,C最后一个字母e,必定是 A 或 C 的最后一个字母组成。

C去除除最后一位,就变成是否可以求出 A-1和B 或者 A与B-1 与 是否可以构成 C-1
 
状态转移方程:

用dp[i][j] 表示 表示A前 i 为 和B 前j 位是否可以组成 C的前i+j位        

        dp[i][j]= (dp[i-1][j]&&(a[i]==c[i+j]))||(dp[i][j-1]&&(b[j]==c[i+j]))

 1 //#define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 bool dp[205][205];
 8 char s1[205], s2[205], s3[410];
 9 
10 int main(void)
11 {
12     #ifdef LOCAL
13         freopen("1501in.txt", "r", stdin);
14     #endif
15 
16     int T, kase;
17     scanf("%d", &T);
18     for(kase = 1; kase <= T; ++kase)
19     {
20         printf("Data set %d: ", kase);
21         cin >> (s1+1) >> (s2+1) >> (s3+1);
22         int len1, len2, len3;
23         len1 = strlen(s1+1);
24         len2 = strlen(s2+1);
25         len3 = strlen(s3+1);
26         if(len1 + len2 != len3)
27         {
28             printf("no\n");
29             continue;
30         }
31         memset(dp, false, sizeof(dp));
32         int i, j;
33         i = 0;
34         while(s1[i] == s3[i])    //处理边界
35             dp[i++][0] = true;
36         i = 0;
37         while(s2[i] == s3[i])
38             dp[0][i++] = true;
39         for(i = 1; i <= len1; ++i)
40             for(j = 1; j <= len2; ++j)
41                 dp[i][j] = ((dp[i-1][j] && s1[i] == s3[i+j])
42                             || (dp[i][j-1] && s2[j] == s3[i+j]));
43 
44 
45         if(dp[len1][len2])
46             printf("yes\n");
47         else
48             printf("no\n");
49     }
50     return 0;
51 }
代码君

 

posted @ 2014-07-31 19:54  AOQNRMGYXLMV  阅读(144)  评论(0编辑  收藏  举报