题意:
输入一个由 "(" 、 ")" 、 "[" 、 "]" 构成的序列,添加尽量少的括号,得到一个规则序列。
//递归结构的动态规划
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<sstream>
#include<map>
#include<stack>
#include<queue>
#include<set>
#include<string>
using namespace std;
char s[201];
int d[101][101],len;
bool match(char a1,char a2){
if(a1=='['&&a2==']') return true;
if(a1=='('&&a2==')') return true;
return false;
}
//d[i][j]表示在s[i..j]中最少需要添加多少括号
/*
如果s[i]和s[j]匹配,则d[i][j] = d[i+1][j-1]
如果j>i,则s[i...j]可以分为两个字符串之和,即d[i][j] = min(d[i][j],d[i][k]+d[k+1][j]) //i<=k<j
d[i][i] = 1;
*/
void dp(){
for(int i = 0;i<len;i++){
d[i][i] = 1;
d[i+1][i] = 0;
}
for(int i = len-2;i>=0;i--){
for(int j = i+1;j<=len-1;j++){//注意循环顺序
d[i][j] = len;
if(match(s[i], s[j])) d[i][j] = min(d[i][j],d[i+1][j-1]);
for(int k = i;k<j;k++) d[i][j] = min(d[i][j],d[i][k]+d[k+1][j]);
}
}
}
//利用d[i][j]来保证输出的括号序列是最优值
void print(int i,int j){//递归打印
if(i>j) return;
if(i==j){//出现 单 个括号,需要补括号!
if(s[i]=='('||s[i]==')') printf("()");
else printf("[]");
return;
}
int ans = d[i][j];
if(match(s[i], s[j])&&ans==d[i+1][j-1]){//如果s[i]和s[j]匹配,则d[i][j] = d[i+1][j-1]
printf("%c",s[i]);
print(i+1, j-1);
printf("%c",s[j]);
return;//注意 return !
}
for(int k = i;k<j;k++){//如果j>i,则s[i...j]可以分为两个字符串之和,即d[i][j] = min(d[i][j],d[i][k]+d[k+1][j]) //i<=k<j
if(ans==d[i][k]+d[k+1][j]){
print(i, k);
print(k+1, j);
return;
}
}
}
int main(){
int T;
cin>>T;
getchar();
while(T--){//输入比较坑。。。
gets(s);
gets(s);
len = strlen(s);
dp();
print(0,len-1);
if(T!=0) puts("");
puts("");
}
return 0;
}