给一个括号序列,可以加括号,求使得其合法的最短的括号序列。
和poj 2955 相似,都是有关合法括号序列,还是区间dp,d[i][j] 表示使得[i,j]合法的最小花费。
然后还要打印处理后的括号序列,递归打印即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[110];
int d[110][110],len;
int match(int i,int j){
return (s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']');
}
int dp(int i,int j){
int & ans = d[i][j];
if(ans != 1e9) return ans;
if(i == j )return ans = 1;
if(i > j) return ans = 0;
if(match(i,j)) ans = min(ans,dp(i+1,j-1));
for(int k = i;k<j;k++) ans = min(ans,dp(i,k)+dp(k+1,j));
return ans;
}
void print(int i,int j){
if(i>j) return ;
if(i == j){
if(s[i]=='(' || s[i] ==')') printf("()");
else printf("[]");
return ;
}
if(match(i,j) && d[i][j] == d[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(d[i][j] == d[i][k] + d[k+1][j]){
print(i,k);
print(k+1,j);
return ;
}
}
}
int main(){
while(gets(s)){
len = strlen(s);
for(int i = 0;i<len;i++) for(int j = 0;j<len;j++) d[i][j] = 1e9;
dp(0,len-1);
print(0,len-1);
printf("\n");
}
return 0;
}