题意:给一个括号序列,最少添加几个括号使该序列成为正规括号序列
按照RujiaLiu的代码写的:
设串至少要增加dp[S]个括号,转移如下:
1)如果S形如(S')或者[S'],转移到dp[S']。
2)如果S至少有两个字符,则可以分成两个部分AB,转移到dp[A]+dp[B]。
注意枚举次序
#include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <iomanip> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define ll long long #define mod 1000000007 #define mem(a) memset(a,0,sizeof(a)) using namespace std; const int maxn = 100 + 5 , inf = 0x3f3f3f3f ; int dp[maxn][maxn]; char s[maxn]; int n; bool ok(char c1,char c2){ if(c1=='('&&c2==')'||c1=='['&&c2==']') return true; return false; } void DP(){ for(int i=0;i<n;i++){ dp[i+1][i] = 0; dp[i][i] = 1; } for(int i=n-2;i>=0;i--){ for(int j=i+1;j<n;j++){ dp[i][j] = n; if(ok(s[i],s[j])) dp[i][j] = min(dp[i][j],dp[i+1][j-1]); for(int k = i;k<j;k++){ dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]); } } } } void print(int i,int j){ if(i>j) return; if(i==j){ if(s[i]=='('||s[i]==')') printf("()"); if(s[i]==']'||s[i]=='[') printf("[]"); return; } int ans = dp[i][j]; if(ok(s[i],s[j])&&ans == dp[i+1][j-1]){ printf("%c",s[i]);print(i+1,j-1);printf("%c",s[j]); return; } for(int k=i;k<j;k++){ if(ans==dp[i][k]+dp[k+1][j]){ print(i,k);print(k+1,j); return; } } } int main(){ int T; scanf("%d",&T); getchar(); while(T--){ mem(s);mem(dp); gets(s); gets(s); n = strlen(s); DP(); print(0,n-1); cout<<endl; if(T) cout<<endl; } return 0; }