POJ 1141 Brackets Sequence 经典区间DP题
记忆化搜索:
View Code
#include<stdio.h> #include<string.h> #include<string> #include<iostream> #include<algorithm> using namespace std; #define inf 1000000000 struct node { int v, vis; // v 表示DP的值,加入的最少的括号个数,vis表示dp这一个状态是否被更新 string s; // 保存要输出的路径, string使用很方便,但时间相当费啊 }dp[103][103]; string s; int dfs(int x, int y) { if(dp[x][y].vis) return dp[x][y].v; if(x == y) { dp[x][y].v = 1, dp[x][y].vis = 1; if(s[x] == '(' || s[x] == ')') dp[x][y].s = "()"; else dp[x][y].s = "[]"; } if(x > y) return 0; if(dp[x][y].vis) return dp[x][y].v; int ans = inf; if(s[x] == '(' && s[y] == ')' || s[x] == '[' && s[y] == ']') { if(ans > dfs(x+1, y-1)) { ans = dp[x+1][y-1].v; dp[x][y].s = s[x] + dp[x+1][y-1].s + s[y]; } } for(int k = x; k <= y-1; k++) { if(ans > dfs(x, k) + dfs(k+1, y)) { ans = dp[x][k].v + dp[k+1][y].v; dp[x][y].s = dp[x][k].s + dp[k+1][y].s; } } dp[x][y].v = ans; dp[x][y].vis = 1; return ans; } int main() { while(getline(cin, s)) { if(s.size()== 0) cout << s <<endl; else { for(int i = 0; i < s.size(); i++) for(int j = 0; j < s.size(); j++) dp[i][j].vis = 0, dp[i][j].v = 0; dfs(0, s.size()-1); cout<<dp[0][s.size()-1].s<<endl; } } return 0; }
递推+递归输出
View Code
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> using namespace std; #define inf 1000000000 string s; int dp[103][103], f[103][103]; //f[][]数组不为-1,表示dp[i][j] 是有两段得来的, //其数值表示合并成一段的中间点 void print(int i, int j)//递归输出 { if(i == j) { if(s[i] == '(' || s[i] == ')') printf("()"); else printf("[]"); return; } if(i > j) return; if(f[i][j] == -1) { printf("%c", s[i]); print(i+1, j-1); printf("%c", s[j]); } else { print(i, f[i][j]); print(f[i][j]+1, j); } } int main() { int i, j, k; while(getline(cin, s)) { if(!s.size()) { cout << endl; continue; } int len = s.size(); for(i = 0; i < len; i++) for(j = 0; j < len; j++) if(i < j) dp[i][j] = inf; else if(i == j) dp[i][j] = 1; else dp[i][j] = 0; memset(f, -1, sizeof(f)); for(int l = 2; l <= len; l++) for(i = 0; i+l-1 < len; i++) { j = i+l-1; if(s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']') if(dp[i][j] > dp[i+1][j-1]) dp[i][j] = dp[i+1][j-1]; for(k = i; k < j; k++) if(dp[i][j] > dp[i][k] + dp[k+1][j]) dp[i][j] = dp[i][k] + dp[k+1][j], f[i][j] = k; } print(0, len-1); puts(""); } return 0; }
递推+递推输出
View Code
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> using namespace std; #define inf 1000000000 string s; int dp[103][103]; string f[103][103]; int main() { int i, j, k; while(getline(cin, s)) { if(!s.size()) { cout << endl; continue; } memset(f, 0, sizeof(f)); int len = s.size(); for(i = 0; i < len; i++) for(j = 0; j < len; j++) if(i < j) dp[i][j] = inf; else if(i == j) { dp[i][j] = 1; if(s[i] == '(' || s[i] == ')') f[i][i] = "()"; if(s[i] == '[' || s[i] == ']') f[i][i] = "[]"; } else dp[i][j] = 0; for(int l = 2; l <= len; l++) for(i = 0; i+l-1 < len; i++) { j = i+l-1; if(s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']') if(dp[i][j] > dp[i+1][j-1]) { dp[i][j] = dp[i+1][j-1]; f[i][j] = s[i] + f[i+1][j-1] + s[j]; } for(k = i; k < j; k++) if(dp[i][j] > dp[i][k] + dp[k+1][j]) { dp[i][j] = dp[i][k] + dp[k+1][j]; f[i][j] = f[i][k] + f[k+1][j]; } } cout << f[0][len-1] << endl; } return 0; }


浙公网安备 33010602011771号