poj 2955 Brackets (区间DP)
题意:View Code View Code
在一些括号中找到一个序列,里面的括号都两两配对。求序列最长长度。
dp[i][j]为i~j的最大括号数,考虑第i个括号,有两种情况:
①不管i直接算dp[i][j] = dp[i + 1][j];★
②枚举i+1~j,找到和i匹配的右括号,有dp[i][j] = max(dp[i][j],dp[i + 1][k - 1] + 2 + dp[k + 1][j])。
递归写法:
1 #include <cstdio>
2 #include <cstring>
3 #define N 105
4
5 int dp[N][N], len, vis[N][N];
6 char s[N];
7
8 int max2(int x, int y)
9 {
10 return x > y ? x : y;
11 }
12
13 int dfs(int i, int j)
14 {
15 if(i>=j || i<1 || j>len) return 0;
16 if(vis[i][j]==1) return dp[i][j];
17 dp[i][j] = dfs(i+1, j);
18 if(s[i]=='(')
19 {
20 for(int x=i+1; x<=j; x++) //x++写成j++
21 {
22 if(s[x]==')')
23 {
24 dp[i][j] = max2(dp[i][j], dfs(i+1,x-1) + dfs(x+1, j) + 2);
25 }
26 }
27 }
28 else if(s[i]=='[')
29 {
30 for(int x=i+1; x<=j; x++)
31 {
32 if(s[x]==']')
33 {
34 dp[i][j] = max2(dp[i][j], dfs(i+1,x-1) + dfs(x+1, j) + 2);
35 }
36 }
37 }
38
39 vis[i][j] = 1;
40 return dp[i][j];
41 }
42
43 int main()
44 {
45 while(scanf("%s",s+1)!=EOF)
46 {
47 if(strcmp(s+1,"end")==0)
48 break;
49 len = strlen(s+1);
50 memset(vis, 0, sizeof(vis));
51 memset(dp, 0, sizeof(dp));
52
53 dfs(1,len);
54 printf("%d\n",dp[1][len]);
55 }
56 return 0;
57 }
2 #include <cstring>
3 #define N 105
4
5 int dp[N][N], len, vis[N][N];
6 char s[N];
7
8 int max2(int x, int y)
9 {
10 return x > y ? x : y;
11 }
12
13 int dfs(int i, int j)
14 {
15 if(i>=j || i<1 || j>len) return 0;
16 if(vis[i][j]==1) return dp[i][j];
17 dp[i][j] = dfs(i+1, j);
18 if(s[i]=='(')
19 {
20 for(int x=i+1; x<=j; x++) //x++写成j++
21 {
22 if(s[x]==')')
23 {
24 dp[i][j] = max2(dp[i][j], dfs(i+1,x-1) + dfs(x+1, j) + 2);
25 }
26 }
27 }
28 else if(s[i]=='[')
29 {
30 for(int x=i+1; x<=j; x++)
31 {
32 if(s[x]==']')
33 {
34 dp[i][j] = max2(dp[i][j], dfs(i+1,x-1) + dfs(x+1, j) + 2);
35 }
36 }
37 }
38
39 vis[i][j] = 1;
40 return dp[i][j];
41 }
42
43 int main()
44 {
45 while(scanf("%s",s+1)!=EOF)
46 {
47 if(strcmp(s+1,"end")==0)
48 break;
49 len = strlen(s+1);
50 memset(vis, 0, sizeof(vis));
51 memset(dp, 0, sizeof(dp));
52
53 dfs(1,len);
54 printf("%d\n",dp[1][len]);
55 }
56 return 0;
57 }
非递归:
dp[i][j] = max(dp[i][x]+dp[x+1][j]) (x:i~j-1)
if(check(i,j)) dp[i][j] = max(dp[i][j], dp[i+1][j-1]+2);
1 #include <cstdio>
2 #include <cstring>
3 #define N 105
4
5 int dp[N][N];
6 char s[N];
7
8 int check(int i, int j)
9 {
10 if((s[i]=='('&&s[j]==')') || (s[i]=='['&&s[j]==']'))
11 return 1;
12 return 0;
13 }
14
15 int max2(int x, int y)
16 {
17 return x > y ? x : y;
18 }
19
20 int main()
21 {
22 while(scanf("%s",s+1)!=EOF)
23 {
24 if(strcmp(s+1,"end")==0) break;
25
26 int len = strlen(s+1);
27 memset(dp, 0, sizeof(dp));
28
29 if(len>=2)
30 for(int i=1; i<=len-1; i++) if(check(i,i+1)) dp[i][i+1] = 2;
31
32 for(int k=3; k<=len; k++)
33 {
34 for(int i=1; k+i-1<=len; i++)
35 {
36 int j = i + k - 1;
37 //dp[i][j] = max2(dp[i+1][j], dp[i][j-1]);
38 if(check(i,j)) dp[i][j] = max2(dp[i][j], dp[i+1][j-1] + 2);
39 //if(check(i,i+1)) dp[i][j] = max2(dp[i][j], dp[i+2][j] + 2);
40 //if(check(j-1,j)) dp[i][j] = max2(dp[i][j], dp[i][j-2] + 2);
41 for(int x = i; x<=j-1; x++) //x=i 与 x=i+1 这里WA
42 dp[i][j] = max2(dp[i][j],dp[i][x]+dp[x+1][j]);
43 }
44 }
45
46 printf("%d\n",dp[1][len]);
47 }
48 return 0;
49 }
2 #include <cstring>
3 #define N 105
4
5 int dp[N][N];
6 char s[N];
7
8 int check(int i, int j)
9 {
10 if((s[i]=='('&&s[j]==')') || (s[i]=='['&&s[j]==']'))
11 return 1;
12 return 0;
13 }
14
15 int max2(int x, int y)
16 {
17 return x > y ? x : y;
18 }
19
20 int main()
21 {
22 while(scanf("%s",s+1)!=EOF)
23 {
24 if(strcmp(s+1,"end")==0) break;
25
26 int len = strlen(s+1);
27 memset(dp, 0, sizeof(dp));
28
29 if(len>=2)
30 for(int i=1; i<=len-1; i++) if(check(i,i+1)) dp[i][i+1] = 2;
31
32 for(int k=3; k<=len; k++)
33 {
34 for(int i=1; k+i-1<=len; i++)
35 {
36 int j = i + k - 1;
37 //dp[i][j] = max2(dp[i+1][j], dp[i][j-1]);
38 if(check(i,j)) dp[i][j] = max2(dp[i][j], dp[i+1][j-1] + 2);
39 //if(check(i,i+1)) dp[i][j] = max2(dp[i][j], dp[i+2][j] + 2);
40 //if(check(j-1,j)) dp[i][j] = max2(dp[i][j], dp[i][j-2] + 2);
41 for(int x = i; x<=j-1; x++) //x=i 与 x=i+1 这里WA
42 dp[i][j] = max2(dp[i][j],dp[i][x]+dp[x+1][j]);
43 }
44 }
45
46 printf("%d\n",dp[1][len]);
47 }
48 return 0;
49 }
WA
1、状态方程不全
2、for()内写错。