[简单DP] POJ 2192 Zipper

给出三个串a b c,问 c 是否能由 a b 串中的字符通过混合得到,要保持同一个串中两个字符的前后关系不变。

状态:f[i ,j] 表示长度为 i 且使用了b串 j 个字符(使用 a 串 i-j 个字符),布尔型,表示状态是否可达。

状态转移: f[i, j] = f[i-1, j] && f[i-1, j-1],对于边界f[0, 0] = true。

也可以令 f[i, j] 为使用了 a 串 i 个字符、b 串j个字符是否可达,如下:

 1 /*

 2     POJ 2192 Zipper

 3 */

 4 # include <cstdio>

 5 # include <cstring>

 6 

 7 using namespace std;

 8 

 9 # define N 200 + 10

10 

11 char a[N], b[N], c[2 * N];

12 char f[N][N];

13 

14 char dp(int n, int m)

15 {

16     f[0][0] = 1;

17     for (int i = 1; i <= n+m; ++i)

18     {

19         for (int j = 0; j <= i && j <= m; ++j)

20         {

21             if (i-j > n) continue;

22             if (!j)

23             {

24                 f[i][0] = (f[i-1][0] & (c[i]==a[i]));

25             }

26             else if (i == j)

27             {

28                 f[0][j] = (f[0][j-1] & (c[j]==b[j]));

29             }

30             else

31                 f[i-j][j] = (f[i-j-1][j]&c[i]==a[i-j]) |

32                             (f[i-j][j-1]&c[i]==b[j]);

33         }

34     }

35     return f[n][m];

36 }

37 

38 void solve(int icase)

39 {

40     int n, m;

41     scanf("%s%s%s", a+1, b+1, c+1);

42     n = strlen(a+1), m = strlen(b+1);

43     printf("Data set %d: ", icase);

44     dp(n, m);

45     puts(f[n][m] ? "yes":"no");

46 }

47 

48 int main()

49 {    

50     int T;

51     

52     scanf("%d", &T);

53     for (int i = 1; i <= T; ++i)

54         solve(i);

55     

56     return 0;

57 }

你可能感兴趣的:(zip)