[简单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 }
原文地址:https://www.cnblogs.com/JMDWQ/p/2621049.html