例题9-10 UVA 1626 Brackets sequence (dp递推 || 记忆化搜索)
来源:互联网 发布:练级的网络手机游戏 编辑:程序博客网 时间:2024/06/06 00:46
大体题意:
括号匹配问题,要求添加尽可能少的括号使得括号匹配 ,其中空括号 是匹配的,括号有[]和()两种!
思路:
dp思想:
令dp[i][j]表示字符串i位置到j位置 最少添加的括号数量!
两种方法 递推和 记忆化搜索思路是一样的,说下整体思路:
如果i和j 这两个位置能匹配的话,那么转移就是ans = min {dp[i+1][j-1]}
然后在类似于最优三角剖分的方法,在中间找一个位置!
使得ans = min{dp[i][k] + dp[k+1][j]}
无论匹配不匹配都要进行第二个转移 ,否则[][]这种情况就转移到了 ][这种情况!!
这样最终会得到 dp每个子字符串所要的括号数量!
然后是打印解!
打印直接递归好了,简单易懂!
如果打印到了边界l == r 那么就要输出一个完整的括号()或者[]
否则 如果 l 和r是匹配的,那么就 递归输出 l+1 到r-1
否则 在找中间位置 满足ans 等于dp[i][j]的,在递归输出!
注意在写递推式时,要注意枚举的方向:
这个也很好理解!
转移是转移dp[i+1][j-1] 第一维向大的方向转移 ,就要从小的位置枚举过来!保证前面的存在!
第二维同理!
不过 递推式的速度是记忆化搜索的五倍左右呢~
详细见代码:
递推式代码:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100 + 10;const int inf = 0x3f3f3f3f;char s[maxn];int dp[maxn][maxn];bool ok(char a,char b){ return a == '[' && b == ']' || a == '(' && b == ')';}void print(int l,int r){ int ans = dp[l][r]; if (l > r)return; if (l == r){ if (s[l] == '(' || s[l] == ')')printf("()"); else printf("[]"); return ; } if (ok(s[l],s[r]) && ans == dp[l+1][r-1]){ printf("%c",s[l]); print(l+1,r-1); printf("%c",s[r]); return; } for (int k = l; k < r; ++k){ if (ans == dp[l][k] + dp[k+1][r]){ print(l,k); print(k+1,r); return; } }}int main(){ int n; scanf("%d%*c",&n); int cnt = 0; while(n--){ gets(s); gets(s); int len = strlen(s); for (int i = 0; i < len; ++i){ dp[i][i] = 1; dp[i+1][i] = 0; } for (int i = len-2; i >= 0; --i){ for (int j = i+1; j < len; ++j){ dp[i][j] = 0x3f3f3f3f; if (ok(s[i],s[j]))dp[i][j] = min(dp[i][j],dp[i+1][j-1]); for (int k = i; k < j; ++k){ dp[i][j] = min(dp[i][j],dp[i][k] + dp[k+1][j]); } } }// printf("%d\n",dp[0][len-1]); if (cnt++)printf("\n"); print(0,len-1); puts(""); } return 0;}
记忆化搜索式代码:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 100 + 10;int len;int dp[maxn][maxn];char s[maxn];bool ok(int i,int j){ return s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']';}int dfs(int l,int r){ int& ans = dp[l][r]; if (ans != -1)return ans; if (l > r)return ans = 0; if (l == r) return ans = 1; ans = 0x3f3f3f3f; if (ok(l,r)){ ans = min(ans,dfs(l+1,r-1)); } for (int k = l; k < r; ++k){ ans = min(ans,dfs(l,k) + dfs(k+1,r)); } return ans;}void print(int l,int r){ int ans = dp[l][r]; if (l > r)return; if (l == r){ if (s[l] == '(' || s[l] == ')')printf("()"); else printf("[]"); return ; } if (ok(l,r) && ans == dp[l+1][r-1]){ printf("%c",s[l]); print(l+1,r-1); printf("%c",s[r]); return; } for (int k = l; k < r; ++k){ if (ans == dp[l][k] + dp[k+1][r]){ print(l,k); print(k+1,r); return; } }}int main(){ int n; scanf("%d%*c",&n); int cnt = 0; while(n--){ gets(s); gets(s); memset(dp,-1,sizeof dp); len = strlen(s); dfs(0,len-1);// printf("%d\n",dp[0][len-1]); if (cnt++)printf("\n"); print(0,len-1); puts(""); } return 0;}
0 0
- 例题9-10 UVA 1626 Brackets sequence (dp递推 || 记忆化搜索)
- UVa #1626 Brackets sequence (例题9-10)
- Ural 1183 Brackets Sequence(区间DP+记忆化搜索)
- UVa 1626:Brackets Sequence(DP)
- ***UVa-1626 Brackets sequence ACM解题报告(巧妙地递推+打印)经典的括号 dp题
- 例题9-10 UVa1626&&POJ1141 Brackets Sequence(DP)
- 【记忆化搜索】POJ-1141 Brackets Sequence
- POJ 2955 Brackets (DP Or 记忆化搜索 总结)
- UVA 1626 - Brackets sequence 区间DP
- uva-1626 Brackets sequence 区间dp
- UVA 1626 Brackets sequence 区间DP
- 1626 - Brackets sequence(DP)
- URAL 1183 Brackets Sequence 记忆化搜索 + DFS
- POJ-1141 Brackets Sequence(递推)
- PKU 1140 - Brackets Sequence (区间dp + 记忆化)
- Uva-1626-Brackets sequence
- UVA 1626 - Brackets sequence
- UVa 1626 Brackets sequence
- 《算竞(紫书)》笔记1 STL入门
- 日文身体部位单词_20161009
- CSS知识归纳—2
- 第七周项目4-队列数组
- 流程控制
- 例题9-10 UVA 1626 Brackets sequence (dp递推 || 记忆化搜索)
- 【Dongle】【数据结构】while循环与for循环
- java---异常处理(1)
- WORDBOOK - ForeverStrong
- WebSocket -- Mongoose
- JSP与数据库
- 面向对象_抽象类练习员工案例
- 复习下json,ajax,地址栏utf-8编码和解码
- 利用Map实现统计一组数字(字母)中每个数字(字母)出现的次数