题目链接:
http://poj.org/problem?id=1141
题目大意:
给一个不完全匹配的括号序列,问最少需要增加多少个括号能够使括号序列完全匹配,输出完全匹配以后的序列。
思路:
区间DP。我们设dp[i][j]代表i~j区间里面使得括号完全匹配最少需要增加的括号数。
那么如果s[i]和s[j]是匹配的,就有dp[i][j]=dp[i+1][j-1]。
然后就在i~j之间枚举k,同时更新dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j])。
这样我们就能够知道最少需要增加的括号数了。接下来我们就要考虑记录路径的问题了。
我们可以设一个p[i][j],初始化为-1。如果p[i][j]=k,就表示在区间i~j里面,在k这个位置有切入点需要添加新的括号。
所以我们可以采用递归的方式,来打印出路径。
代码:
#include<stdio.h> #include<string.h> char s[105],c[105]; int p[105][105]; void print(int i,int j) { if(i>j)return; if(i==j){ if(s[i]=='('||s[i]==')')printf("()"); else printf("[]"); return; } if(i<j) { if(p[i][j]==-1){ if(s[i]=='(') { printf("("); print(i+1,j-1); printf(")"); } else if(s[i]=='['){ printf("["); print(i+1,j-1); printf("]"); } } else { print(i,p[i][j]); print(p[i][j]+1,j); } } } int main() { int dp[105][105],i,j,k,l; while(gets(c)) { l=strlen(c); for(i=0;i<l;i++) s[i+1]=c[i]; memset(dp,0,sizeof(dp)); memset(p,-1,sizeof(p)); for(i=1;i<=l;i++) dp[i][i]=1; for(k=2;k<=l;k++) { for(i=1;i<=l-k+1;i++) { int zhong=i+k-1; if(s[i]=='('&&s[zhong]==')'||s[i]=='['&&s[zhong]==']') {dp[i][zhong]=dp[i+1][zhong-1]; p[i][zhong]=-1;} else dp[i][zhong]=99999999; for(j=i;j<zhong;j++) { if(dp[i][zhong]>dp[i][j]+dp[j+1][zhong]) { dp[i][zhong]=dp[i][j]+dp[j+1][zhong]; p[i][zhong]=j; } } } } // printf("%d\n",l); print(1,l); printf("\n"); } return 0; }