poj 1141 Brackets Sequence

                                                                                                                     Brackets Sequence
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 32662   Accepted: 9441   Special Judge

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

()[()]

Source

思路:DP,见代码。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char s[1101];
int f[1101][1101],c[1101][1101];
void print(int l,int r){
    if(l>r)    return ;
    if(l==r)
        if(s[l]=='('||s[l]==')')    printf("()");
        else printf("[]");
    else
        if(c[l][r]>=0){
            print(l,c[l][r]);
            print(c[l][r]+1,r);
        }
        else{
            if(s[l]=='('){
                printf("(");
                print(l+1,r-1);
                printf(")");
            }
            else{
                printf("[");
                print(l+1,r-1);
                printf("]");
            }
        }
}
int main(){
    gets(s);
    int len=strlen(s);
    for(int i=0;i<len;i++)    f[i][i]=1;
    for(int i=0;i<len;i++)
        for(int j=0;j<len;j++)
            c[i][j]=-1;
    for(int l=1;l<len;l++)
        for(int i=0;i+l<len;i++){
            int j=i+l;
            int minn=f[i][i]+f[i+1][j];
            c[i][j]=i;
            for(int k=i+1;k<j;k++){
                if(minn>f[i][k]+f[k+1][j])    c[i][j]=k;//枚举断点
                minn=min(minn,f[i][k]+f[k+1][j]);
            }
            f[i][j]=minn;
            if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']')){
                if(f[i][j]>f[i+1][j-1])    c[i][j]=-1;
                f[i][j]=min(f[i][j],f[i+1][j-1]);
            }
         }
    print(0,len-1);
    cout<<endl;
}
/*
d[i][j]为输入序列从下标i到下标j最少需要加多少括号才能成为合法序列。0<=i<=j<len (len为输入序列的长度)。
c[i][j]为输入序列从下标i到下标j的断开位置,如果没有断开则为-1。
当i==j时,d[i][j]为1
当s[i]=='(' && s[j]==')' 或者 s[i]=='[' && s[j]==']'时,d[i][j]=d[i+1][j-1]
否则d[i][j]=min{d[i][k]+d[k+1][j]}(i<=k<j)c[i][j]记录断开的位置k
采用递推方式计算d[i][j]

输出结果时采用递归方式输出print(0, len-1)
输出函数定义为print(int i, int j),表示输出从下标i到下标j的合法序列
当i>j时,直接返回,不需要输出
当i==j时,d[i][j]为1,至少要加一个括号,如果s[i]为'(' 或者')',输出"()",否则输出"[]"
当i>j时,如果c[i][j]>=0,说明从i到j断开了,则递归调用print(i, c[i][j]);和print(c[i][j]+1, j);
        如果c[i][j]<0,说明没有断开,如果s[i]=='(' 则输出'('、 print(i+1, j-1); 和")"
                                    否则输出"[" print(i+1, j-1);和"]"
*/ 

 

posted @ 2017-09-01 19:01  一蓑烟雨任生平  阅读(135)  评论(0编辑  收藏  举报