uva1626 Brackets sequence
题目大意:
给一个有小括号和中括号组成的序列,满足题中的三个条件时,是合法的。不满足时是不合法的,问将一个不合法的序列最少添加几个括号可以使之变成合法的。输出最短合法序列。
/* 比较坑的一道题,wa无数次。。。 思路就是区间dp的一般思路,dp[i][j]表示区间i~j之间最少加几个字符才能匹配成立 pre[i][j]表示在区间i~j中的两个子区间左端点 */ #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int inf=1<<29; const int maxn=110; char str[maxn]; int n,dp[maxn][maxn]; pair<int,int>pre[maxn][maxn]; bool check(int i,int j){ if((str[i]=='('&&str[j]==')')||str[i]=='['&&str[j]==']') return true; return false; } void dfs(int l,int r){ if(l>r)return; if(l==r){ if(str[l]=='['||str[l]==']')printf("[]"); if(str[l]=='('||str[l]==')')printf("()"); return; } if(check(l,r)&&dp[l][r]==dp[l+1][r-1]){ printf("%c",str[l]); dfs(l+1,r-1); printf("%c",str[r]); return; } int sl=pre[l][r].first; int sr=pre[l][r].second; dfs(sl,sr); dfs(sr+1,r); } int main(){ freopen("Cola.txt","r",stdin); int T; scanf("%d",&T); getchar(); while(T--){ memset(pre,-1,sizeof(pre)); gets(str); gets(str); n=strlen(str); for(int i=0;i<n;i++)dp[i][i]=1; for(int j=1;j<n;j++){ for(int i=0;i+j<n;i++){ dp[i][i+j]=inf; if(check(i,i+j)){ dp[i][i+j]=dp[i+1][i+j-1]; pre[i][i+j]=make_pair(i+1,i+j-1); } for(int k=0;k<=j;k++){ if(dp[i][i+j]>dp[i][i+k]+dp[i+k+1][i+j]){ dp[i][i+j]=dp[i][i+k]+dp[i+k+1][i+j]; pre[i][i+j]=make_pair(i,i+k); } } } } dfs(0,n-1); printf("\n"); if(T)printf("\n"); } return 0; }