题意:
给出T个字符串,仅由 ‘(’ ‘)’ ‘[’ ‘]’ 四种 字符组成,其中 ’()‘ ‘[]’为合法,’()[]’ ‘([])’ ‘[()]’ 均为合法,而’[(])‘ ‘[)’ 则为不合法状态。求最少添加多少个字符,使得字符串合法,输出合法的其中一种方案。(原始字符串字符不多于100个)
第一行为字符串数量。
样例输入:
1
([(]
样例输出:
()[()]
思路:
1.前后配对的为dp[i][j]=min(dp[i][j],dp[i+1][j-1])
2.字符串至少两个以上时,进行二分,k=i:j-1,dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j])
无论字符串满不满足第一条,都要进行第二条运算,反例:s=”[][]”,如果只进行第一步得到的是’][‘最后还需要再加两个括号,这是不符合题目最小的要求的。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max = 100;
const int INF = 0x3f3f3f3f;
int N;
char S[Max + 5];
int Dp[Max + 5][Max + 5];
bool Match(int a, int b){
if((S[a] == '(' && S[b] == ')') || (S[a] == '[' && S[b] == ']'))
return 1;
return 0;
}
void Print(int l, int r){
if(l > r) return ;
if(l == r){
if(S[l] == '(' || S[l] == ')') printf("()");
else printf("[]");
return ;
}
if(Match(l, r) && Dp[l][r] == Dp[l + 1][r - 1]){
printf("%c", S[l]);
Print(l + 1, r - 1);
printf("%c", S[r]);
return ;
}
for(int k = l; k < r; ++ k) if(Dp[l][r] == Dp[l][k] + Dp[k + 1][r]){
Print(l, k);
Print(k + 1, r);
return ;
}
}
int main(){
int T, flg = 0;
cin>>T;
getchar();
while(T --){
gets(S);
gets(S);
N = strlen(S);
if(! N){
if(flg ++) putchar(10);
putchar(10);
continue;
}
for(int i = 0; i < N; ++ i)
Dp[i][i] = 1;
for(int i = N - 1; i >= 0; -- i){
for(int j = i + 1; j < N; ++ j){
Dp[i][j] = INF;
if(Match(i, j))
Dp[i][j] = min(Dp[i][j], Dp[i + 1][j - 1]);
for(int k = i; k < j; ++ k)
Dp[i][j] = min(Dp[i][j], Dp[i][k] + Dp[k + 1][j]);
}
}
if(flg ++) putchar(10);
Print(0, N - 1);
putchar(10);
}
return 0;
}
还有需要注意的地方就是,输入串可能为空,所以不能用scanf之类的输入。