POJ 1141 区间DP
给一组小括号与中括号的序列,加入最少的字符,使该序列变为合法序列,输出该合法序列。
dp[a][b]记录a-b区间内的最小值,
mark[a][b]记录该区间的最小值怎样得到。
#include "stdio.h" #include "string.h" int inf=99999999; char str[110]; int dp[110][110],mark[110][110]; void pri(int l,int r) { if (l>r) return ; if (l==r) { if(str[l]=='(' || str[r]==')') printf("()"); if(str[l]=='[' || str[r]==']') printf("[]"); return ; } if (mark[l][r]==-1) { printf("%c",str[l]); pri(l+1,r-1); printf("%c",str[r]); } else { pri(l,mark[l][r]); pri(mark[l][r]+1,r); } } int main() { int i,j,k,a,b,n; while (gets(str)) { n=strlen(str); if (n==0) { printf("\n"); continue; } for (i=0;i<n;i++) for (j=0;j<n;j++) if (i>=j) dp[i][j]=0; else dp[i][j]=inf; for (i=0;i<n;i++) dp[i][i]=1; for (j=2;j<=n;j++) for (i=0;i<=n-j;i++) { a=i; b=i+j-1; if (str[a]=='(' && str[b]==')') { dp[a][b]=dp[a+1][b-1]; mark[a][b]=-1; } if (str[a]=='[' && str[b]==']') { dp[a][b]=dp[a+1][b-1]; mark[a][b]=-1; } for (k=a;k<b;k++) if (dp[a][k]+dp[k+1][b]<dp[a][b]) { dp[a][b]=dp[a][k]+dp[k+1][b]; mark[a][b]=k; } } pri(0,n-1); printf("\n"); } return 0; }