UVA1626-Brackets sequence(動態規劃基礎)
阿新 • • 發佈:2018-11-10
Problem UVA1626-Brackets sequence
1
([(]
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
([(]
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 }