1. 程式人生 > >UVA1626-Brackets sequence(動態規劃基礎)

UVA1626-Brackets sequence(動態規劃基礎)

Problem UVA1626-Brackets sequence

Time Limit: 4500 mSec

Problem Description

 

 

 

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

()[()]

 

題解:這個題挺好的,區間dp,可以寫成記憶化搜尋,容易忽略的地方是如果區間兩邊的括號匹配,那麼可以用中間的部分轉移,然後就是普通的分成左區間和右區間進行轉移,這個題比較有價值的地方在於列印解的過程,應該學習一下,就是根據結果,逆推回去,這個方便在不用中間記錄轉移路徑,代價就是時間上會有額外的開銷,不過一般不至於因此就TLE,因為解一般很少。輸入輸出有坑,需要用fgets,並且注意fgets會把最後的'\n'讀進來,因此真實串的長度需要-1.

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 100 + 10;
 6 
 7 int iCase, dp[maxn][maxn];
 8 char bra[maxn];
 9 bool vis[maxn][maxn];
10 
11 bool match(char a, char b) {
12     if ((a == '(' && b == ')') || (a == '[' && b == ']')) return true;
13     return false;
14 }
15 
16 int DP(int l, int r) {
17     if (dp[l][r] >= 0) return dp[l][r];
18     if (l == r) return dp[l][r] = 1;
19     if (l > r) return  dp[l][r] = 0;
20 
21     int &ans = dp[l][r];
22     ans = r - l + 1;
23     if (match(bra[l], bra[r])) {
24         ans = min(ans, DP(l + 1, r - 1));
25     }
26     for (int k = l; k < r; k++) {
27         ans = min(ans, DP(l, k) + DP(k + 1, r));
28     }
29     return ans;
30 }
31 
32 void ans_print(int l, int r) {
33     if (l > r) return;
34     if (l == r) {
35         if (bra[l] == '(' || bra[l] == ')') {
36             printf("()");
37         }
38         else {
39             printf("[]");
40         }
41         return;
42     }
43 
44     int &ans = dp[l][r];
45     if (match(bra[l], bra[r]) && ans == dp[l + 1][r - 1]) {
46         printf("%c", bra[l]);
47         ans_print(l + 1, r - 1);
48         printf("%c", bra[r]);
49         return;
50     }
51     else {
52         for (int k = l; k < r; k++) {
53             if (ans == dp[l][k] + dp[k + 1][r]) {
54                 ans_print(l, k);
55                 ans_print(k + 1, r);
56                 return;
57             }
58         }
59     }
60 }
61 
62 int main()
63 {
64     //freopen("input.txt", "r", stdin);
65     scanf("%d\n", &iCase);
66     while (iCase--) {
67         fgets(bra, maxn, stdin);
68         memset(dp, -1, sizeof(dp));
69         int len = strlen(bra);
70         int ans = DP(0, len - 2);
71         ans_print(0, len - 2);
72         printf("\n");
73         if (iCase) printf("\n");
74         fgets(bra, maxn, stdin);
75     }
76     return 0;
77 }