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 }
代码君

 

你可能感兴趣的:(zip)