这周主要学习了动态规划。
动态规划用于解决多阶段决策最优化问题。
理论基础是R.Bellman的“最优化原理”(Principle of optimality):“一个过程的最优决策具有这样的性质:即无论其初始状态和初始决策如何,其今后诸策略对以第一个决策所形成的状态作为初始状态的过程而言,必须构成最优策略”。
动态规划的适用条件:(1)状态必须满足最优化原理; (2)状态必须满足无后效性。可以通过考察是否具有最优子结构和重叠子问题来判断能否使用动态规划。(算法导论第15章)
动态规划是一种思想而不是算法,没有一个固定的框架。一般过程为:(1)划分阶段 (2)确定状态和状态变量 (3)确定决策并写出状态转移方程 (4)寻找边界条件 (5)程序设计实现
最重要的是状态转移方程,能写出方程那么该问题就完成了一大半。
动态规划简洁高效,是一种非常优美的方法。值得深入研究学习。
本周做的题目:
POJ 3624 Charm Bracelet:基本的01背包问题。状态转移方程f[i][v]=max{f[i-1][v],f[i-1]
[v-c[i]]+w[i]}
POJ 2109 Power of Cryptography:水题。还以为要高精度。其实直接用double型,然后pow()算一下就好。唉,基础也不会了,汗……
POJ 1887 Testing the CATCHER:最长不上升子序列。分析可以得到状态转移方程f[i] = max{f[j]:j<I, height[i]<=height[j]}+1。还是蛮基础的题目。只是一开始以为是最长下降子序列。缺了个“=”号。结果郁闷很久,一直找不出错。最后还是雷同学提醒。要仔细看题目啊!
POJ 2533 Longest Ordered Subsequence:最长上升子序列。f[i] = max{f[j]:j<I, number[i]>numb
er[j]}+1。把1187的代码改一下,3分钟AC掉。
POJ 1458 Common Subsequence:LCS,而且只要求长度。非常基础。还记得一开始看算导的时候觉得LCS很难懂,现在回来再做思路清晰了很多,空间上也能做出一些优化。看来最近的学习还是略有所得。不过一开始数组开的小了,结果WA了一次。开1000就可以过。
POJ 1050 To the Max:最大子段和问题。先看一维情况。给定一维数组a[1]…a[n],构造和数组maxn[i]=max{0,maxn[i-1]}+a[i]。那么maxn中保存的最大值就是一维数组的最大子段。可以把二维压缩成一维。构造数组sum[i][j]=sum[i-1][j]+a[i][j]。则a[k][j]+…+a[i][j]=sum[i][j]-
sum[k][j]。让k由0至i-1进行循环。那么根据最大子段和的公式就能遍历得到所有以i结束的子矩阵和。其中最大值就是最大子矩阵的和。这是一个O(n^3)的算法。
这周一直感冒,做的题不多,都是DP的基础。
今天ACM队招新比赛。我去现场做一下指导之类的。虽然蛮辛苦,但感觉挺好。很多同学报名参加,我觉得现在的水平如何并不重要,一开始的时候我也和他们一样连EOF怎么用都不明白,关键在于是否喜欢编程,能否坚持做下去。希望我们学校的ACM队伍能逐渐壮大起来,能取得良好的成绩。我也要努力做出一些贡献吧。
下一周应该会继续做DP的题目,再加一些图论。