题意:给一个括号序列,要求把这个括号序列变成全部匹配的序列,要求补充的括号字符最少
题解:这道题是区间DP,我们考虑这样一个状态,F[ i ][ j ] 表示把 i 到 j 这一段完全匹配所要添加的最小括号数,在每拓展到下一位时,有两种情况:1、这个新的符号无法和前面的任何一个匹配,只能添加一个新的符号和它匹配,那么F[ i ][ j ] = F[ i + 1][ j ] + 1; 2、新的字符能与 i + 1 到 j 中的字符匹配,那么F[ i ][ j ] = F[i + 1][k - 1] + F[ k ][ j ]; 然后两者取最小值。然后记录一下路径,输出。
CODE:
/*
Author: JDD
PROG: poj1141 Brackets Sequence
DATE: 2015.10.12
*/
#include <cstdio>
#include <cstring>
#define REP(i, s, n) for(int i = s; i <= n; i ++)
#define REP_(i, s, n) for(int i = n; i >= s; i --)
#define MAX_N 505
using namespace std;
char s[MAX_N];
int F[MAX_N][MAX_N], a[MAX_N][MAX_N];
bool b[MAX_N];
void Gao(int i, int j)
{
if(i >= j) return;
if(a[i][j] == -1) b[i] = 0, Gao(i + 1, j);
if(a[i][j] > 0){
b[i] = 1; b[a[i][j]] = 1;
Gao(i + 1, a[i][j] - 1); Gao(a[i][j], j);
}
}
void doit()
{
int n = strlen(s);
n --;
printf("%d\n", n);
REP(i, 1, n) F[i][i] = 1;
REP_(i, 1, n - 1) REP(j, i + 1, n){
F[i][j] = F[i + 1][j] + 1;
a[i][j] = -1;
REP(k, i + 1, j){
if((s[i] == '(' && s[k] == ')') || (s[i] == '[' && s[k] == ']'))
if(F[i][j] > F[i + 1][k - 1] + F[k][j] - 1)
F[i][j] = F[i + 1][k - 1] + F[k][j] - 1,
a[i][j] = k;
}
}
Gao(1, n);
REP(i, 1, n){
if(b[i]) printf("%c", s[i]);
else{
if(s[i] == '(' || s[i] == ')') printf("()");
else printf("[]");
}
}
printf("\n");
}
int main()
{
while(gets(s + 1) > 0){
s[0] = 2;
memset(F, 0, sizeof(F));
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
doit();
}
return 0;
}