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;
}

 

posted @ 2015-10-12 16:07  ALXPCUN  阅读(143)  评论(0编辑  收藏  举报