括号匹配问题 区间DP经典问题

题目链接 http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=15

给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的

分析:要求要添加多少个,可以求出最大匹配的长度,这样剩下的都是没有匹配的,所以每个对于一个匹配就可以了。

即 答案 = 字符串长度 - 最大匹配长度。

首先考虑怎么样定义dp让它满足具有通过子结构来求解、

定义dp [ i ] [ j ] 为串中第 i 个到第 j 个括号的最大匹配数目

那么我们假如知道了 i 到 j 区间的最大匹配,那么i+1到 j+1区间的是不是就可以很简单的得到。

那么 假如第 i 个和第 j 个是一对匹配的括号那么dp [ i ] [ j ] = dp [ i+1 ] [ j-1 ] + 2 ;

那么我们只需要从小到大枚举所有 i 和 j 中间的括号数目,然后满足匹配就用上面式子dp,然后每次更新dp [ i ] [ j ]为最大值即可。

更新最大值的方法是枚举 i 和 j 的中间值,然后让 dp[ i ] [ j ] = max ( dp [ i ] [ j ] , dp [ i ] [ f ] + dp [ f+1 ] [ j ] ) ;

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <string>
 5 #include <algorithm>
 6 using namespace std;
 7 #define maxn 110
 8 int N, dp[maxn][maxn];
 9 string s;
10 int main(){
11     scanf("%d", &N);
12     
13     while(N--){
14         memset(dp, 0, sizeof(dp));
15         cin>>s;
16         for(int len = 1; len < s.size(); len++){
17             for(int i = 0, j = len; j < s.size(); i++,j++){
18                 if(s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']')
19                     dp[i][j] = dp[i+1][j-1] + 2;
20                 for(int k = i; k < j; k++)
21                     dp[i][j] = max(dp[i][j] , dp[i][k] + dp[k][j]);
22             }
23         }
24         printf("%d\n", s.size()-dp[0][s.size()-1]);
25         
26     }
27     
28     return 0;
29 }

类似题 POJ 2955   http://poj.org/problem?id=2955

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <string>
 5 #include <algorithm>
 6 using namespace std;
 7 #define maxn 110
 8 int N, dp[maxn][maxn];
 9 string s;
10 int main(){
11     while(cin>>s){
12         if(s == "end") break;
13         memset(dp, 0, sizeof(dp));
14         
15         for(int len = 1; len < s.size(); len++){
16             for(int i = 0, j = len; j < s.size(); i++,j++){
17                 if(s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']')
18                     dp[i][j] = dp[i+1][j-1] + 2;
19                 for(int k = i; k < j; k++)
20                     dp[i][j] = max(dp[i][j] , dp[i][k] + dp[k][j]);
21             }
22         }
23         printf("%d\n", dp[0][s.size()-1]);
24         
25     }
26     
27     return 0;
28 }

 

posted @ 2015-03-17 17:38  下周LGD该赢了吧  阅读(181)  评论(0编辑  收藏  举报