动态规划之LIS && ZigZag && BadNeighbors
来源:互联网 发布:淘宝主图背景图模板 编辑:程序博客网 时间:2024/06/07 19:34
题目背景
- 第一个LIS,最长非递减序列,这个大家应该很熟悉了吧。不用具体叙述。
- 第二个是TopCoder中的题目,附上网址,请点击我
理由
为什么将两者结合一起,主要是因为,所用的方法是在本质上是一样的。
首先说一下题目特征:
- 首先都是在一维的层次上,属于初级递推公式
- 都是以数组a[]作为输入,阶段的划分是以离散时间作为节点,在这两个程序中,我用的都是dp[]作为递推的结果记录,记录每个节点的最长纪录,但是最后的结果取所有记录的最大值
- 属于离散随机的动态规划,离散指的是时间,随机指的是决策过程
- 都是从bottom-up策略
- 边界从最开始给出
- 状态变量就是每个阶段的状态值,在这里是每个阶段的最优的状态变量
- 区别:第一个用了一个dp[]就可以完成工作;第二个由于题目的要求,需要增加结构描述,完全是为了方便,第二个就用flag[]记录了,在另一层次的阶段的状态
- 决策集合就是在节点之前的都可以作为决策集合,但是可以减少决策集合的数量,通过强约束条件,如第二个题目temp*flag[i]<=0 && dp[i] < dp[j+1] + 1
- 第二题我用了三种方法进行推演,由于第一种特别的麻烦,而且很不容易想,所以有了第二个版本,但是第二个版本也是不容易演算,所以有了第三个版本;改进的策略就是将一些特判的东西进行一般化,用一个一般化的公式就可以算出,就像阶段策略一样,阶段是为了解决问题而产生的一个像生物进化的东西,随着每次演化到下一阶段,则更接近我们寻求的结果。
- 这个程序需要注意的就是初始状态如何与一般状态组合起来;技巧:其实如果数组中出现相同的值,其实可以自动忽略,因为不会起任何的作用,我的前两个程序就是没有考虑到,以为不用忽略,最后一个也是研究了国外的大神代码才看出来的,下面把他的代码和网址贴出来:
int longestZigZag( vector <int> sequence ) { int n = sequence.size(); vector <int> dp (n, 1); vector <int> dif (n, 0); int temp; for (int i = 1; i < n; i++) for (int j = 0; j < i; j++) { temp = sequence[i] - sequence[j]; if (temp != 0 && temp*dif[j] <= 0 && dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; dif[i] = temp; } } sort (dp.begin(), dp.end()); return dp[n-1];}
网址
BadNeighbors
题目网址
先说一下思路:
刚看到题目的时候,以为就和ZigZag思路一样的,所以就直接省略了思考DP的前面步骤,直接写出来了递推公式,最后运行case,发现{ 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 }无论如何得出结果都是15,经过仔细观察还是发现了题目的tricky,因为题目要求的是Circle型算法,而我只是考虑了StraightLine型。
递归公式1:
a[]为输入串
定义dp[i]为以当前阶段以a[i]为结尾的最大的捐赠
这个dp相对有点麻烦,对于这个问题,因为最后求最大的不是最后一个dp[n-1], 下面会有改进的递推公式。
KeyPoints: 因为这还只是个StraightLine型,为了变成Circle,由于第一个元素和最后一个元素是连续的,所以用了一个技巧,就是利用忽视第一个元素算到最后一个元素的dp1[]和从第一个元素算到倒数第二个元素的dp2[],最后比较两个dp*中的最大值即可。
return max{dp1[0~n-2], dp[1~n-1]};
代码:
int maxDonations(int a[], int n){ int maxValue = 0; int * dp1 = new int[n]; int * dp2 = new int[n]; dp1[0] = a[0]; dp1[1] = (a[1]>a[0]?a[1]:a[0]); if (n == 2) return maxValue = dp1[1]; dp2[1] = a[1]; dp2[2] = (a[2]>a[1]?a[2]:a[1]); maxValue = (dp2[2]>dp1[1]?dp2[2]:dp1[1]); for(int i = 2; i < n -1; i++) { dp1[i] = a[i]; for(int j = 0; j < i; j++) { if(( j%n != (i-1)%n) && dp1[j]+a[i]>dp1[i]) { dp1[i] = dp1[j] + a[i]; } } if(dp1[i] > maxValue) { maxValue = dp1[i]; } } for(int i = 3; i < n; i++) { dp2[i] = a[i]; for(int j = 1; j < i; j++) { if(( j%n != (i-1)%n) && dp2[j]+a[i]>dp2[i]) { dp2[i] = dp2[j] + a[i]; } } if(dp2[i] > maxValue) { maxValue = dp2[i]; } } return maxValue;}
递归公式2:
a[]为输入串
定义dp[i]为以当前阶段到a[i]的最大捐赠,可以不包括a[i],这一点与上面不同。
int maxDonations(int a[], int n){ int maxValue = 0; int * dp = new int[n]; dp[0] = a[0]; dp[1] = a[1]>a[0]?a[1]:a[0]; if(n == 2) return maxValue = dp[1]; for(int i = 2; i < n -1; i++) { if(a[i] + dp[i-2] > dp[i-1]) dp[i] = a[i] + dp[i-2]; else dp[i] = dp[i-1]; } maxValue = dp[n-2]; dp[2] = a[2]>a[1]?a[2]:a[1]; for(int i = 3; i < n; i++) { if(a[i] + dp[i-2] > dp[i-1]) dp[i] = a[i] + dp[i-2]; else dp[i] = dp[i-1]; } if(maxValue < dp[n-1]) maxValue = dp[n-1]; return maxValue;}
参考网址
后续还有很多,比如说二维的动态规划,更高阶,暂时写到这……
0 0
- 动态规划之LIS && ZigZag && BadNeighbors
- UVA10534-----Wavio Sequence-----动态规划之LIS
- 动态规划之LCS和LIS
- 动态规划总结之 LIS ,LCS
- 动态规划---LIS
- 动态规划---LIS
- 动态规划 LCS,LIS
- 动态规划-LIS
- 动态规划 LIS
- Sicily LIS |动态规划
- 动态规划--LIS练习
- 动态规划 — LIS
- 合唱队形(LIS) 动态规划
- hdu1087 动态规划入门LIS
- 动态规划--LIS与LCS
- BadNeighbors
- BadNeighbors
- dp学习之BadNeighbors解法
- Android中Activity之间切换动画的修改
- 图像局部特征学习(笔记1之具有尺度不变性的Harris角点)
- Hibernate 4.0+MySql5.5 无法自动创表
- 针对ArcGIS Server 跨域问题的解释
- AS边学边写——day01序章和开发前的准备
- 动态规划之LIS && ZigZag && BadNeighbors
- 旋转字符串
- java__网络编程UDP
- SQL Server2005允许远程访问连接的设置方法
- 什么是GemFire
- Myeclipse中WEB-INF和META-INF文件夹的各文件含义
- Linux内核:seek机制
- PL/SQL Developer连接Oracle数据库,最简便的配置方法
- 自己用10分钟写了一个猜数字的小游戏娱乐室友