题意:
括号由( )或者[ ]组成..并且当s为一个合法的括号序列...那么(s)和[s]都是合法的括号序列..现在给出一列括号..请添加最少的括号让这个括号序列合法.并且输出添加过括号后合法的括号序列..
题解:
容易想到区间DP...dp[l][r]代表将区间[l~r]变成合法的括号序列所需添加的最少括号数...初始值对于每个位置dp[i][i]=1..转移..若当前s[l]可以和s[r]配对..则先将其赋值为dp[l+1][r-1].(注意..比如dp[1][2]时..会变成dp[2][1]..所以初始时将所有的dp[ ][ ]初始成0)...否则其先赋值为无穷大..然后枚举终点k=l~r-1...看dp[l][k]+dp[k+1][r]能否将dp[l][r]更新得更小..那么更新...如此得到了整个区间所需要的最少添加括号次数...
而要输出合法的括号序列..就需要一边更新一边转移了...为了输出的方便...用递归回朔很直接..
Program:
#include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> #include<time.h> #include<map> #include<math.h> #include<queue> #define MAXN 105 #define MAXM 1000005 #define oo 1000000007 #define ll long long #define MOD 1000000 using namespace std; char s[MAXN]; int dp[MAXN][MAXN],pre[MAXN][MAXN]; void dfs(int l,int r) { if (l>r) return; if (l==r) { if (s[l]=='(' || s[l]==')') printf("()"); else printf("[]"); return; } int x=pre[l][r]; if (!x) printf("%c",s[l]), dfs(l+1,r-1), printf("%c",s[r]); else dfs(l,x),dfs(x+1,r); } int main() { int n,i,L,l,r,k; freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); gets(s+1),n=strlen(s+1); memset(dp,0,sizeof(dp)); memset(pre,0,sizeof(pre)); for (i=1;i<=n;i++) dp[i][i]=1; for (L=2;L<=n;L++) for (l=1;l<=n-L+1;l++) { r=l+L-1; if (s[l]=='(' && s[r]==')' || s[l]=='[' && s[r]==']') dp[l][r]=dp[l+1][r-1]; else dp[l][r]=oo; for (k=l;k<r;k++) if (dp[l][r]>dp[l][k]+dp[k+1][r]) { dp[l][r]=dp[l][k]+dp[k+1][r]; pre[l][r]=k; } } dfs(1,n); printf("\n"); // printf("%d\n",dp[1][n]); return 0; }