区间DP POJ 1141 Brackets Sequence

Brackets Sequence
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 29520   Accepted: 8406   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

()[()]
    
 1 /*对于DP题目需要记录到底是怎样得到结果的,不一定了可以通过记录信息直接得到,可以选择数组记录其他有用信息,可以写递归来找出最后的答案。*/
 2 #define N 111
 3 #include<iostream>
 4 using namespace std;
 5 #include<cstring>
 6 #include<cstdio>
 7 #define inf (1<<31)-1
 8 int f[N][N],pos[N][N],lens;
 9 char s[N];
10 void print(int l,int r)/*输出序列的过程*/
11 {
12     if(l<=r)/*一定要有这一句,否则对于相邻的‘()’,就会死循环了*/
13     {
14         if(l==r)/*能到这一步,说明只能补上括号了*/
15         {
16             if(s[l]=='('||s[l]==')') printf("()");
17             if(s[l]=='['||s[l]==']') printf("[]");
18         }
19         else 
20         {
21             if(pos[l][r]==-1)/*说明该区间最左括号与最右匹配*/
22             {
23                 printf("%c",s[l]);
24                 print(l+1,r-1);/**/
25                 printf("%c",s[r]);
26             }
27             else 
28             {
29                 print(l,pos[l][r]);
30                 print(pos[l][r]+1,r);
31             }
32         }
33     }
34 }
35 int main()
36 {
37 //    freopen("bracket.in","r",stdin);
38 //    freopen("bracket.out","w",stdout);
39     scanf("%s",s+1);
40     lens=strlen(s+1);
41     for(int i=1;i<=lens;++i)
42       f[i][i]=1;
43 /*    for(int i=lens-1;i>=1;--i)
44       for(int j=i+1;j<=lens;++j)
45       {
46             f[i][j]=inf;
47             if(((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']')))
48               {
49                   f[i][j]=f[i+1][j-1];
50                   pos[i][j]=-1;
51             }
52                                 
53             for(int k=i;k<=j-1;++k)
54             {
55             if(f[i][j]>f[i][k]+f[k+1][j])
56             {
57                     f[i][j]=f[i][k]+f[k+1][j];
58                     pos[i][j]=k;
59             }
60             
61           }
62           
63       }这两种都是可以得出正确答案的,但是我建议使用下面的,对于区间DP,最外层循环最好枚举区间长度,内层枚举区间*/
64     for(int k=1;k<lens;++k)
65       for(int i=1,j=i+k;j<=lens&&i<=lens;++j,++i)
66       {
67             f[i][j]=inf;
68             if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']'))
69               {
70                   f[i][j]=f[i+1][j-1];
71                   pos[i][j]=-1;
72             }
73                  /*不要加else,因为即使当前区间的最左和最右匹配,也不一定比放弃他们匹配优*/
74             for(int k=i;k<=j-1;++k)
75             {
76             if(f[i][j]>f[i][k]+f[k+1][j])
77             {
78                     f[i][j]=f[i][k]+f[k+1][j];
79                     pos[i][j]=k;
80             }
81             
82           }
83           
84       }
85     print(1,lens);
86     printf("\n");/*坑爹的POJ,没有这句,一直没对*/
87     //fclose(stdin);fclose(stdout);
88     return 0;
89 }

 

posted @ 2016-05-15 21:24  csgc0131123  阅读(166)  评论(0编辑  收藏  举报