题目描述
设
f(i,j)
为将区间i~j变成正规括号序列需要加的最少括号数。
f(i,j)=min(f(i,k)+f(k+1,j))
当s[i]和s[j]是一对括号时,还可以作如下转移:
f(i,j)=min(f(i,j),f(i+1,j−1))
边界为
f(i,i)
=1,
f(i+1,i)=0
;
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char s[400];
int f[110][110],p[110][110],l;
void print(int i,int j){
if(i>j) return;
if(i==j){
if(s[i]=='['||s[i]==']') printf("[]");
else printf("()");
}else if(p[i][j]==l){
putchar(s[i]);
print(i+1,j-1);
putchar(s[j]);
}else{
print(i,p[i][j]);
print(p[i][j]+1,j);
}
}
void readline(char* S) {
fgets(S, 108, stdin);
}
int main(){
int n;
readline(s);
sscanf(s, "%d", &n);
readline(s);
while(n--){
readline(s);
l=(int)strlen(s)-1;
for(int i=0;i<l;i++)
for(int j=0;j<l;j++)
f[i][j]=10000;
for(int i=0;i<l;i++){
f[i][i]=1;
if(i>0) f[i][i-1]=0;
}
for(int k=1;k<l;k++){
for(int i=0;i+k<l;i++){
if((s[i]=='('&&s[i+k]==')')||(s[i]=='[' &&s[i+k]==']')){
if(f[i+1][i+k-1]<f[i][i+k]){
f[i][i+k]=f[i+1][i+k-1];
p[i][i+k]=l;
}
}
for(int j=0;j<k;j++){
if(f[i][i+j]+f[i+j+1][i+k]<f[i][i+k]){
f[i][i+k]=f[i][i+j]+f[i+j+1][i+k];
p[i][i+k]=i+j;
}
}
}
}
print(0, l-1);
printf("\n");
if(n) printf("\n");
readline(s);
}
return 0;
}
这里我用了一个p数组保存答案,p[i][j]=l时说明f[i][j]从f[i+1][j-1]转移过来的,否则就从f[i][p[i][j]]+f[p[i][j]+1][j]转移过来。
另外输入是个坑,,,我也是参考别人的输入才AC的,,