poj 2955 Brackets (区间DP)

题意:

在一些括号中找到一个序列,里面的括号都两两配对。求序列最长长度。

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]==1return 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, 0sizeof(vis));
51         memset(dp, 0sizeof(dp));
52 
53         dfs(1,len);
54         printf("%d ",dp[1][len]);
55     }
56     return 0;
57 }
View Code

 非递归:

 

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")==0break;
25 
26         int len = strlen(s+1);
27         memset(dp, 0sizeof(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 ",dp[1][len]);
47     }
48     return 0;
49 }
View Code

WA

 1、状态方程不全

 2、for()内写错。

原文地址:https://www.cnblogs.com/byluoluo/p/3561819.html