括号序列
问题 C: 括号序列
时间限制: 1 Sec 内存限制: 128 MB提交: 109 解决: 56
[提交][状态][讨论版]
题目描述
定义如下规则序列(字符串):
1.空序列是规则序列;
2.如果S是规则序列,那(S)和[S]也是规则序列;
3.如果A和B都是规则序列,那么AB也是规则序列。
例如,下面的字符串都是规则序列:
(), [],
(()), ([]), ()[], ()[()]
这几个不是规则序列:
(, [, ],
)(, ([()
现在,给出一些有'('
, ')' , '[' , ']'组成的序列,请添加尽量少的括号,得到一个规则序列,并输出该序列的长度。
输入
输入一个有'(' , ')' , '[' , ']'组成的序列,长度不超过200
输出
输出规则后的字串长度
样例输入
([(]
样例输出
6
提示
([()])//6
这题也是一道分段类DP,如果l,r两个边界刚好为一对,及为()或[],这样的话则dp[l][r]=dp[l+1][r-1]。
然后再枚举中间点,记忆化,或者for循环形式都是可以的,我个人的话练了练for的形式,记忆化比较好理解。
#include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<cstring> #include<string> using namespace std; const int MAXN=207; char s[MAXN]; int dp[MAXN][MAXN]; bool match(char c1,char c2) { if ((c1=='('&&c2==')')||(c1=='['&&c2==']')) return true; return false; } int main() { scanf("%s",s); int len=strlen(s); int n=len; memset(dp,0,sizeof(dp)); for (int i=1;i<=len;i++) dp[i][i]=1; for (int i=1;i<len;i++) if (match(s[i-1],s[i])) dp[i][i+1]=0; else dp[i][i+1]=2; for (int t=2;t<=n-1;t++) for (int i=1;i<=n-t;i++) { if (match(s[i-1],s[i+t-1])) dp[i][i+t]=dp[i+1][i+t-1]; else dp[i][i+t]=MAXN*MAXN*MAXN; for (int j=0;j<=t-1;j++) dp[i][i+t]=min(dp[i][i+t],dp[i][i+j]+dp[i+j+1][i+t]); } printf("%d",dp[1][len]+len); }