poj1141 动态规划
来源:互联网 发布:去除图片马赛克软件 编辑:程序博客网 时间:2024/06/05 09:29
1、空串是regular brackets sequence
2、如果S是regular brackets sequence,则[S]和(S)也是regular brackets sequence
3、如果A、B都是regular brackets sequence,则AB也是regular brackets sequence
一些regular brackets sequence例子
(), [], (()), ([]), ()[], ()[()]
一些非regular brackets sequence例子
(, [, ), )(, ([)], ([(]
问题:现在给出一个序列,要你通过添加括号来将给出的序列变成regular brackets sequence
样例
Sample Input
([(]
Sample Output
()[()]
题解:这题乍看时没啥思路,虽然自己是最近在练习动态规划,但是不知道怎么往dp上想,自己思维能力太菜了,o(︶︿︶)o 唉!!!没辙,网上找题解,一看自己傻眼了,这么容易的dp式子自己就是想不到,脑子这硬伤如何修复啊T_T
其实这题的动态转移方程和常规,设置一个dp[i,j]表示从第i个字符到第j个字符要形成一个regular brackets sequence需要添加的最少字符数(想了想,自己之所以没想到这个状态表示是因为被题目给迷惑,老想着怎么添加括号,没想着关键因素:添加最少的括号数。其实如果知道一个区间内最少需要添加的括号数,具体怎么添加也就不在话下了,有点事后诸葛的意思:))
好了,表示好了状态之后,就需求如何进行状态转移
我们可以将区间就行划分,然后要使总区间的括号数最少,就得选择一个划分状态,使得划分开的两边最少括号数之和最小,这里需要用到一点分治的思路,大问题通过划分成几个小问题来求解,其实动态规划也就是一种可以解决分治算法重复求解某些状态的方法。
①dp[i,j] = min{dp[i,k] + dp[k+1,j]} (i<=k<j)
这里需要注意,上面的状态转移方程还有一种情况没有考虑,就是当i和j正好是一对匹配括号时,我们需要另外设置一个状态转移方程②dp[i,j] = dp[i+1,j-1]。
做到这里我又有点想当然了,认为如何满足条件②的话,就不必再求条件①,这是一种很不严谨的思路,我们找不到任何方法说明它是正确的,反而可以找到一组反例,假设给出的序列是()(),如果用这种思路的话,肯定需要添加的最少括号数为2,输出的结果是()()()。所以以后碰到类似情况的时候,除非确定某些情况是最优的,不然一定要所有情况都进行比较取最优。
下面贴下代码
- #include <stdio.h>
- #include <string.h>
- #define N 101
- #define INF 0x7fffffff
- char Brackets[N];
- int dp[N][N];
- int path[N][N];
- bool Match(char a, char b)
- {
- if ((a == '[' && b == ']') || (a == '(' && b == ')'))
- return 1;
- return 0;
- }
- void PrintBracket(char c)
- {
- if (c == '[' || c == ']')
- printf("[]");
- else if (c == '(' || c == ')')
- printf("()");
- }
- void PrintPath(int l, int r)
- {
- if (l > r)
- return;
- if (l == r)
- PrintBracket(Brackets[l-1]);
- else
- {
- if (path[l][r] == -1)
- {
- printf("%c", Brackets[l-1]);
- PrintPath(l+1, r-1);
- printf("%c", Brackets[r-1]);
- }
- else
- {
- PrintPath(l, path[l][r]);
- PrintPath(path[l][r] + 1, r);
- }
- }
- }
- void MinLenSubSeq()
- {
- int i;
- int j;
- int k;
- int len = strlen(Brackets);
- for (i = 1; i <= len; i++)
- {
- dp[i][i] = 1;
- dp[i][i-1] = 0;
- }
- memset(path, -1, sizeof(path));
- for (k = 1; k < len; k++)
- {
- for (i = 1; i + k <= len; i++)
- {
- j = i + k;
- int t;
- dp[i][j] = INF;
- for (t = i; t < j; t++)
- {
- int bracket_num = dp[i][t] + dp[t+1][j];
- if (bracket_num < dp[i][j])
- {
- dp[i][j] = bracket_num;
- path[i][j] = t;
- }
- }
- if (Match(Brackets[i-1], Brackets[j-1]) && dp[i+1][j-1] < dp[i][j])
- {
- dp[i][j] = dp[i+1][j-1];
- path[i][j] = -1;
- }
- }
- }
- //printf("minimal possible length is %d\n", dp[1][len]);
- PrintPath(1, len);
- printf("\n");
- }
- int main(void)
- {
- int i;
- while (gets(Brackets))
- {
- MinLenSubSeq();
- }
- return 0;
- }
- POJ1141 动态规划
- poj1141 动态规划
- poj1141 动态规划
- POJ1141 动态规划,空间优化
- poj1141 Brackets Sequence 动态规划 输出路径
- POJ1141 ZOJ1463 Brackets Sequence 经典动态规划 区间DP
- POJ1141 Brackets Sequence (dp动态规划,递归)
- 动态规划入门(三)DP 基本思想 具体实现 经典题目 POJ1159 POJ1458 POJ1141
- poj1141
- poj1141
- poj1141
- poj1141
- poj1141
- poj1141
- poj1141
- poj1141
- poj1141
- 动态规划!!!动态规划!!!
- 2013年让你不掉队的东西
- 跟linux编辑器vi一样强大--windows环境下的vim编辑器
- XML Web Service
- MFC 各种小问题记录
- HTTP基本概念
- poj1141 动态规划
- 提取FLV视频文件中的音频到MP3文件(代码)
- ios 加入声音效果
- Spring2.5教程:7、Spring+JDBC组合开发和事务
- hive的server模式
- 10步让你成为更优秀的程序员
- 认识与分析Linux登录文件
- c/c++ main 函数命令行参数的使用 知识小结
- Hadoop简介