zoukankan      html  css  js  c++  java
  • POJ 1141 Brackets Sequence (区间DP)

    Description

    Let us define a regular brackets sequence in the following way:

    1. Empty sequence is a regular sequence.
    2. If S is a regular sequence, then (S) and [S] are both regular sequences.
    3. If A and B are regular sequences, then AB is a regular sequence.

    For example, all of the following sequences of characters are regular brackets sequences:

    (), [], (()), ([]), ()[], ()[()]

    And all of the following character sequences are not:

    (, [, ), )(, ([)], ([(]

    Some sequence of characters '(', ')', '[', and ']' is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.

    Input

    The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.

    Output

    Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.

    Sample Input

    ([(]

    Sample Output

    ()[()]


    题意:给一串括号序列。依照合法括号的定义,加入若干括号,使得序列合法。

    典型区间DP。设dp[i][j]为从i到j须要加入最少括号的数目。

    dp[i][j] = max{ dp[i][k]+dp[k+1][j] }  (i<=k<j)

    假设s[i] == s[j] , dp[i][j] 还要和dp[i+1][j-1]比較。 枚举顺序依照区间长度枚举。

    由于要求输出合法序列,就要记录在原序列在哪些位置进行了添加,设c[i][j]为从i到j的 添加括号的位置,假设不须要添加。那么c[i][j] 赋为-1,打印时仅仅需递归打印就可以。


    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    typedef long long LL;
    const int MAX=0x3f3f3f3f;
    int n,c[105][105],dp[105][105];
    char s[105];
    void print(int i,int j) {
        if( i>j ) return ;
        if( i == j ) {
            if(s[i] == '(' || s[i] == ')') printf("()");
            else printf("[]");
            return ;
        }
        if( c[i][j] > 0 ) {  // i到j存在添加括号的地方,位置为c[i][j]
            print(i,c[i][j]);
            print(c[i][j]+1,j);
        } else {
            if( s[i] == '(' ) {
                printf("(");
                print(i+1,j-1);
                printf(")");
            } else {
                printf("[");
                print(i+1,j-1);
                printf("]");
            }
        }
    }
    void DP() {   //区间DP
        for(int len=2;len<=n;len++)
            for(int i=1;i<=n-len+1;i++) {
                int j = i+len-1;
                for(int k=i;k<j;k++) if( dp[i][j] > dp[i][k]+dp[k+1][j] ) {
                    dp[i][j] = dp[i][k] + dp[k+1][j];
                    c[i][j] = k;  // 记录断开的位置
                }
                if( ( s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']' ) && dp[i][j] > dp[i+1][j-1] ) {
                    dp[i][j] = dp[i+1][j-1];
                    c[i][j] = -1;  //i到j不须要断开。由于dp[i+1][j-1]的值更小,上面枚举的k位置都比这个大。所以不再断开
                }
            }
    }
    int main()
    {
        scanf("%s",s+1);
        n = strlen(s+1);
        memset(c,-1,sizeof(c));
        memset(dp,MAX,sizeof(c));
        for(int i=1;i<=n;i++) dp[i][i] = 1, dp[i][i-1] = 0; //赋初值
        DP();
        print(1,n);
        printf("
    ");
        return 0;
    }
    



    
  • 相关阅读:
    寒假学习第九天
    寒假学习第八天
    寒假学习第七天
    寒假学习第六天
    寒假学习第五天
    寒假学习第四天
    寒假学习第三天
    寒假学习第二天
    寒假学习第一天
    阅读笔记
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7236097.html
Copyright © 2011-2022 走看看