[DP] UVA-1626 Brackets sequence

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 a1a2 . . . an is called a subsequence of the string b1b2 . . . bm, if there exist such indices 1 ≤ i1 < i2 < . . . < in ≤ m, that aj = bij for all 1 ≤ j ≤ n.

 

Input

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

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

 

Output

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

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

1

([(]

 

Sample Output

()[()]

 

题意:

定义如下序列为合法的括号序列:

1、空序列为合法序列

2、若S是合法序列,则(S), [S]也为合法序列

3、若A、B均为合法序列,则AB也为合法序列

题目给出一个括号序列,添加最少的(, ), [, ]使序列合法。

 

思路:本题是经典的区间DP,思想是不断分割小区间,直到出现(S)或[S]时,状态转移到S,即从dp[i][j]转移到dp[i + 1][j - 1]。

PS:该题的读入和输出很坑,需要注意

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int opt[501][501],f[501][501];
 5 char str[501];
 6 void print(int left,int right)
 7 {
 8     if (left > right) return;
 9     else
10     if (left == right)
11     {
12         if ((str[left] == '[') || (str[right] == ']')) printf("[]");
13         else printf("()");    
14     }
15     else
16         if (f[left][right] == -1)
17         {
18             printf("%c",str[left]);
19             print(left + 1,right - 1);
20             printf("%c",str[right]);
21         }
22         else
23         {
24             print(left,f[left][right]);
25             print(f[left][right] + 1,right);
26         }
27 }
28 int main()
29 {
30     int t,len,i,j,k,l,Case;
31     char s[101],ch;
32     scanf("%d",&t);
33     scanf("%c",&ch);
34     for (Case = 1;Case <= t;Case++)
35     {
36         scanf("%c",&ch);
37         gets(str);
38         len = strlen(str);
39         if (len == 0)
40         {
41             printf("\n");
42             if (Case != t) printf("\n");
43             continue;
44         }
45         memset(opt,0,sizeof(opt));
46         memset(f,0,sizeof(f));
47         for (i = 0;i < len;i++) opt[i][i] = 1;
48         for (l = 1;l < len;l++)
49         {
50             for (i = 0;i < len - l;i++)
51             {
52                 j = i + l;
53                 opt[i][j] = 999999999;
54                 if (((str[i] == '(') && (str[j] == ')')) || ((str[i] == '[') && (str[j] == ']')))
55                 {
56                     opt[i][j] = opt[i + 1][j - 1];
57                     f[i][j] = -1;
58                 }
59                 for (k = i;k < j;k++)
60                 {
61                     if (opt[i][j] > opt[i][k] + opt[k + 1][j])
62                     {
63                         opt[i][j] = opt[i][k] + opt[k + 1][j];
64                         f[i][j] = k;
65                     }
66                 }
67             }
68         }
69         print(0,len - 1);
70         printf("\n");
71         if (Case != t) printf("\n");
72     }
73 }

 

转载于:https://www.cnblogs.com/Suwako1997/p/7265673.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值