能用动态规划解决的问题,肯定能用搜索解决。但是搜素时间复杂度太高了,怎么优化呢?你想到了记忆化搜索,就是搜完某个解之后把它保存起来,下一次搜到这个地方的时候,调用上一次的搜索出来的结果。这样就解决了处理重复状态的问题。动态规划之所以速度快是因为解决了重复处理某个状态的问题。记忆化搜索是动态规划的一种实现方法。搜索到i状态,首先确定要解决i首先要解决什么状态。那么那些状态必然可以转移给i状态。于是你就确定了状态转移方程。然后你需要确定边界条件。将边界条件赋予初值。此时就可以从前往后枚举状态进行状态转移拉。
动态规划
我在学习算法的时候,就被动态规划搞得是一头雾水,这几日终于是弄明白是怎么回来。
明白之后我才发觉我以前就碰到过一道ACM题,大意是这样的:
有这样形式的一种排列:
例如:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
从顶至下找一条路径,使得这条路径上的数字之和最大,而且每一步只能向左下或右下找,直到到最后一行。
比如:第二行的3只能找第三行8或者1。
上面例子的最大一条路径是:7-3-8-7-5;总和30(原题:http://acm.fzu.edu.cn/problem.php?pid=1004)
如果按照贪婪算法,从上往下找,则最佳路径应该是7-8-1-7-5;总和28
可见贪婪算法在此是行不通的。我们可以试着从下往上找,倒数两行:
2 7 4 4
4 5 2 6 5
我们先对最后一行相邻的两个数字进行比较,大的加到上一行的数字上。则4-5比较5较大则倒数第二行2+5;
5-2比较5较大,则倒数第二行7+5,如此类推:则倒数第二行就是:
7 12 10 10;
然后依此类推:直到第一行,就得到了最大的和,当然原题没有要求我们找路径,所以不用记录路径.
其实这就是一种动态规划的应用。
它与贪婪法的区别,在此也能明显地看出:
1:贪婪法,采取的是自顶向下,逐步找局部最优,从而来达到,整体最优.
而动态规划则是从下往上倒推,
2:贪婪法,在进行决策时并不依赖于上一步的决策。每一步的决策都是单独的,确定的,不可回遡的。
比如在找第一行7的下一个节点,那肯定是第二行的8,它是确定的,不可回遡的。而第二行的8的下一个结点肯定是1,它并不依赖于上一步的决策,
而动态规划则是不同的,它的每一步进行决策时是依赖于上一步的决策的。每一步的决策的相关的,是可回遡的。
比如在找第一行7的下一个节点,它能有两个种决策,一个是第二行的3,一个是第二行的8。由于有这两种可能性,所以在进行,第二行至第三行的决策的时候,是依赖于上一步决策的。而且由于每一次决策所以产生的可能的状态,都被保荐着,所以当所以找的决策不是最优决策时,可以回遡。
越说越麻烦了,一句话,就是动态规划其实是以牺牲空间来换取决策的正确性.
动态规划步骤: 划分阶段;选择状态; 确定决策;写出状态转移方程;写出规划方程(包括边界条件)
下面是简单的例子。
状态: F[i][j]
状态转移方程:F[i][j] = a[i][j]+max(F[i+1][j], F[i+1][j+1])
边界条件:当i = n时,F[i][j] = a[i][j];
其中,F[i][j]表示状态,而我认为a[i][j]就是阶段,当前走到了a[i][j]的阶段,而做何决策,就看max函数的返回值了,而做完了这个决策,他的状态就会变成F[i][j].
总结 状态、阶段、决策 经过一系列组合 会组合成 状态转移方程.但是,这些东西并不是都显示出现的.所以,分清阶段、状态、决策是非常重要的。