给一个只含有()[]的序列添加最少的符号使括号成为正规序列
如果s可以分成[s']或(s')则转移到s'状态,然后对于区间[j, l]将区间分成两部分, dp[j][l] = min(dp[j][l], dp[j][k] + dp[k + 1][l]), j < k < l;
在处理过程中用c[i][j]记录区间[i, j]最优的分割点, 如果值为-1表示按第一种方式转移最佳,借助c数组递归输出最优解。
#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
int dp[110][110], c[110][110];
char s[110];
void dfs(int b, int e) {
if(b > e)
return;
if(b == e) {
if(s[b] == '(' || s[b] == ')')
printf("()");
else printf("[]");
}
else if(c[b][e] == -1) {
printf("%c", s[b]);
dfs(b + 1, e - 1);
printf("%c", s[e]);
}
else {
dfs(b, c[b][e]);
dfs(c[b][e] + 1, e);
}
}
int main() {
int t, n, i, j, k;
scanf("%d%*c", &t);
while(t--) {
getchar();
gets(s);
n = strlen(s);
memset(dp, 0, sizeof(dp));
memset(c, -1, sizeof(c));
for(i = 0; i < n; i++)
dp[i][i] = 1;
for(i = 1; i < n; i++) {
for(j = 0; j < n - i; j++) {
int l = j + i;
if((s[j] == '(' && s[l] == ')') || (s[j] == '[' && s[l] == ']'))
dp[j][l] = dp[j + 1][l - 1];
else dp[j][l] = INF;
for(k = j; k < l; k++) {
if(dp[j][l] > dp[j][k] + dp[k + 1][l]) {
dp[j][l] = dp[j][k] + dp[k + 1][l];
c[j][l] = k;
}
}
}
}
dfs(0, n - 1);
printf("\n");
if(t) printf("\n");
}
return 0;
}