标签:
挺简单的
先谈状态 dp[i][j]表示i---j之间的最少需要加的括号数
再谈转移 if S 为 合法序列 那么 (S),[S] 都为合法序列,那么dp[i][j] = dp[i +1][j - 1];
if A 为合法序列 && B为合法序列 那么 AB 为合法序列 dp[i][j] = dp[i][k] + dp[k + 1][j];
所以代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 #define REP(i,N) for (int i = 0;i < (N);i++) 7 #define REP_1(i,N) for (int i = 1;i < (N);i++) 8 #define REP_2(i,be,en) for (int i = (be);i < (en);i++) 9 #define DWN(i,N) for (int i = (N);i >= 0;i--) 10 #define DWN_1(i,N) for (int i = (N);i >= 1;i--) 11 #define DWN_2(i,en,be) for (int i = (en);i >= (be);i--) 12 #define INF 0x7fffffff 13 #define MAXN 110 14 15 using namespace std; 16 17 typedef long long LL; 18 char ch[MAXN]; 19 int dp[MAXN][MAXN]; 20 21 bool match(char ch1,char ch2) { 22 return (ch1 == ‘(‘ && ch2 == ‘)‘) || (ch1 == ‘[‘ && ch2 == ‘]‘); 23 } 24 25 void print(int i,int j) { 26 if (i > j) return; 27 if (i == j) { 28 if (ch[i] == ‘(‘ || ch[i] == ‘)‘) printf("()"); 29 else printf ("[]"); 30 return; 31 } 32 int ans = dp[i][j]; 33 if (match(ch[i],ch[j]) && ans == dp[i + 1][j - 1]) { 34 cout << ch[i];print(i + 1,j - 1);cout << ch[j]; 35 return; 36 } 37 REP_2(k,i,j) { 38 if (ans == dp[i][k] + dp[k + 1][j]) { 39 print(i,k); 40 print(k + 1,j); 41 return; 42 } 43 } 44 } 45 46 int main () { 47 int T; 48 //freopen("1.txt","r",stdin); 49 cin >> T; 50 getchar();getchar(); 51 while (T--) { 52 fgets(ch,MAXN,stdin); 53 int LEN = strlen(ch) - 1; // fgets读入了回车,所以 -1 54 memset(dp,0,sizeof(dp)); 55 REP(i,LEN) dp[i][i] = 1; 56 REP_1(i,LEN) { 57 DWN(j,i - 1) { 58 dp[j][i] = LEN; 59 if (match(ch[j],ch[i])) dp[j][i] = min(dp[j][i],dp[j + 1][i - 1]); 60 REP_2(k,j,i) { 61 dp[j][i] = min(dp[j][i],dp[j][k] + dp[k + 1][i]); 62 } 63 } 64 } 65 print(0,LEN - 1); 66 cout << endl; 67 if (T) cout << endl; 68 fgets(ch,MAXN,stdin); 69 } 70 }
uva 1626(动态规划起步第五天 LIS变形 括号匹配)
标签:
原文地址:http://www.cnblogs.com/xiaoshanshan/p/4296996.html