NYOJ 15 括号匹配(区间dp)
2017-07-22 15:26
399 查看
跟括号匹配(一)截然不同 二 不在考栈的应用了 这道题是一道区间dp
这道题写了很久 自己没写出来 参考了网上超过15篇博客才算是略知一二
本文提供两种解法
方法一:
定义dp[i][j] 为从位置I到位置j所需要的括号数量 状态转移的过程是这样的 枚举I和j 或者长度 如果第I个点和第j个点匹配 那么 dp[i][j] 是不是应该等于min(dp[I][j], dp[I + 1][j - 1]) 呢
如果不匹配那么我们可以枚举I到j中间所有的点 尝试是否能松弛 其实是尝试能否减小dp[I][j] 类似于松弛的操作 对就是这样 值得注意的是边界问题 和 dp数组的初始化问题
单独的一个位置dp[i][I]应该初始化为多少呢 没错 初始化为1 需要一个额外的括号使之匹配 差不多这样
方法二 :如果我们能找到这一串括号中的最大匹配量 那么需要额外添加的括号就是长度减去最大匹配量
稍微更改下方法一的代码就能得到方法二的代码 建议先看懂方法一在看方法二
这道题写了很久 自己没写出来 参考了网上超过15篇博客才算是略知一二
本文提供两种解法
方法一:
定义dp[i][j] 为从位置I到位置j所需要的括号数量 状态转移的过程是这样的 枚举I和j 或者长度 如果第I个点和第j个点匹配 那么 dp[i][j] 是不是应该等于min(dp[I][j], dp[I + 1][j - 1]) 呢
如果不匹配那么我们可以枚举I到j中间所有的点 尝试是否能松弛 其实是尝试能否减小dp[I][j] 类似于松弛的操作 对就是这样 值得注意的是边界问题 和 dp数组的初始化问题
单独的一个位置dp[i][I]应该初始化为多少呢 没错 初始化为1 需要一个额外的括号使之匹配 差不多这样
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int maxn = 105; const int inf = 0x3f3f3f3f; int main() { int t, dp[maxn][maxn]; char str[maxn]; cin >> t ; while ( t -- ) { cin >> str ; int length = strlen(str); for (int i = 0; i < length; i ++) { for (int j = 0; j < length ; j ++) { if(i < j) dp[i][j] = inf; else if (i == j)dp[i][j] = 1; else dp[i][j] = 0; } }//len 不从0开始是因为枚举长度为0没有意义 for (int len = 1; len < length; len ++) {//len表示从i开始的一段长度为len的区间 for (int i = 0; i < length - len; i ++) {//i表示区间的起点 int j = len + i;//j表示区间的终止点 if(str[i] == '(' && str[j] == ')' || str[i] == '[' && str[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]); } } cout << dp[0][length - 1] << endl; } }
方法二 :如果我们能找到这一串括号中的最大匹配量 那么需要额外添加的括号就是长度减去最大匹配量
稍微更改下方法一的代码就能得到方法二的代码 建议先看懂方法一在看方法二
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int maxn = 105; const int inf = 0x3f3f3f3f; int main() { int t, dp[maxn][maxn]; char str[maxn]; cin >> t ; while ( t -- ) { cin >> str ; int length = strlen(str); memset(dp , 0, sizeof(dp)); for (int len = 1; len < length ; len ++) {//len依旧枚举长度 for (int i = 0; i < length - len; i ++) {//i为起点 int j = len + i;//终点 if(str[i] == '(' && str[j] == ')' || str[i] == '[' && str[j] == ']') dp[i][j] = dp[i + 1][j - 1] + 2;//如果匹配 那么当前区间的值肯定是一个较小的区间的值+2来的 for (int k = i; k < j; k ++)//松弛过程 dp[i][j] = max(dp[i][j] , dp[i][k] + dp[k + 1][j]); } } cout << length - dp[0][length - 1] << endl; } }
相关文章推荐
- nyoj 括号匹配(二) 15 (区间dp) 好题
- NYOJ 15 括号匹配(二) POJ 2955 Brackets(区间dp)
- nyoj 15 括号匹配(二)(区间DP)
- NYOJ15:括号匹配(二)(区间dp)
- NYOJ 15-括号匹配(二)(经典区间DP)
- nyoj 15 括号匹配(二)(区间DP)
- NYOJ15 括号匹配(二)(区间dp)
- NYOJ15括号匹配(=)区间DP
- NYOJ 15 括号匹配(二)(区间dp)
- nyoj 15 括号匹配(二)(区间DP)
- NYOJ 15 括号匹配(二)区间dp
- nyoj-15 括号匹配(二)区间dp
- nyoj 15 括号匹配(二)(区间DP)
- NYOJ15-括号匹配(二)-区间DP
- [poj2955/nyoj15]括号匹配(区间dp)
- nyoj 15 括号匹配(二)(区间DP)
- nyoj 15 括号匹配(二)(区间DP)
- 区间dp 括号匹配 nyoj 15
- nyoj 15 括号匹配(二)(区间DP)
- NYOJ15 - UVA1626 括号匹配问题(区间dp)