动态规划入门

一种学习编程的方法:抄别人的思路,抄别人的代码,然后,变成自己的。
我在微博上看不少牛人都用过这样的方法,我以前也用,只不过没说。哈哈,这种方法适合比较难的算法。而,动态规划对我来说,就是比较难的了。算法,我觉得自己上道儿没多久。 一直听说动态规划是一种很牛的算法,确切的说是一种方法。我对它一直都是望而却步,一方面没有实际需求,另一方面总觉得自己学不会。这不要练内功,就硬着头皮开始,并且使出我上面的招数。 (本来前几天就要开始的,结果杭电acm上不去了,真郁闷,今天我不得不转战北大的acm。以后可能这儿吧,至少这里稳定啊,不会像杭电那样,总挂。这样,我这个春节回家,也算有点儿成绩了) 原来或多或少接触过动态规划,从别人的只言半语中,我觉得动态规划就是把一些需要重复计算的结果,存储起来,或者说缓存起来,这样,就可以不需要重复计算。但是,在实际运用中,我这招儿好想不灵,我觉得应该是问题本身的原因,如果大量重复得子问题,缓存的思想,肯定也能够提速不少的。既然如此,就说说正规的动态规划。
自顶向下的分析问题,自底向上的解决问题。
这是动态规划方法的要诀,解决问题的时候,都应该按照这个来进行。在使用这个要诀进行分析之前,首先要明确,什么样的问题,能过用动态规划的方法解决:
  1. 最优子结构性质。意思是,要解决最优问题,可以通过找到其子问题的最优解来进行。这是一个递归的过程,但是学术一点儿说:要满足最优化原理
  2. 子问题重叠性质。就是在递归的过程中,每次遇到的子问题,不一定都是新的,可能已经计算过了,那这样再此计算就是浪费。
具备上面两个性质的问题,我们就可以采用动态规划来解决。第一个理解递归的,就比较好理解。第二个呢,还需要深入分析一下。记得看过网易公开课,课中将到,求解fibonacci数列,如果采用递归的方法,当计算fib(6)的时候,函数调用25次,而采用动态规划的方法,需要11次。这里,使用动态规划带来的好处,并不明显,25次很小,11次再稍微小一点儿。但是,当我们计算fib(30)的时候,如果是递归的方法,需要调用2692537次,而动态规划,只需要调用59次。这就看到巨大的差距了。所以,当我们应用动态规划方法的时候,我们也要去考虑,真的值得使用,是参数为6的情况,还是参数为30的情况?毕竟,动态规划的代码,要比递归要复杂,要更难阅读。这意味着在实际中,维护成本增加。 下面,通过POJ的几个入门级的题目,理解动态规划。 POJ1163 这个题目比较有意思。如下图: 遍历这棵二叉树,当然每次只能选择左右子树其中一个。要找到一条路径,从根到叶子的路径上的所有数字和最大,输出最大数字即可。 分析:首先要寻找最优子结构,确定递归的形式。忽略中间过程,最终会有五个值,因为是五个叶子节点。得到这五个值之后,比较一下,最大的就出来,那这每个值如何得到呢?此处就可以产生递归形式和最优子结构。要表示这个二叉树,可以用一个二维数组a[n][2n - 1]。这个很好理解,那a[n][1]=4,所以:

a[n][1] = max(a[n - 1][2]) + a[n][1]------①

递归形式出来了,要求得到a[n][1]节点的最大和,就要求得到a[n - 1][2](本来的值为2)节点的最大和,再加上a[n][1]本来的值就可以了。

再看a[n][3]怎么处理(a[n][2] = 0),递归形式如下:

a[n][3] = max(a[n - 1][2], a[n - 1][ 3 + 1]) + a[n][3]-------②

②与①有一点儿不一样。差别就在a[n][3]的父节点有两个,而 a[n][1]只有一个。

现在递归形式找到了,那么子问题重叠问题呢?通过①和②很明显的看出来,他们重复计算了a[n - 1][2]。其实,如果,我们把计算的过程都列出来,重复计算也是指数级增长的。可充分利用动态规划的长处。

核心代码如下:

for (int i = 1; i <= n; ++i) {
			for (int j = 1; j < n + n; ++j) {
				if (i == 1 || 0 == values[i][j]) continue;
				int max = 0;
				if (j > 1 && values[i - 1][j - 1] > max)
					max = values[i - 1][j - 1];
				if (j < n + n - 1 && values[i - 1][j + 1] > max) 
					max = values[i - 1][j + 1];
				values[i][j] = max + values[i][j];
			}
		}

后面还有几个例子,今天一共ac了四个题目,会慢慢写出来分析。

【引用】

http://v.163.com/movie/2010/6/8/1/M6TCSIN1U_M6TCT9E81.html

http://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92

 

posted on 2012-01-29 17:32  sing1ee  阅读(332)  评论(0)    收藏  举报