POJ1141 Brackets Sequence
题意:给一个括号序列,要求把这个括号序列变成全部匹配的序列,要求补充的括号字符最少
题解:这道题是区间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; }