漫谈算法 动态规划 Dynamic Programming

Dynamic Programming一直以来是自己比较弱的一部分,希望可以在这一块有所提升。
动态规划,Dynamic Programming。这里的programming没有翻译成编程,是因为,这里的programming的意思是指一个tabular method。其实这也暗示了DP的本质,用一个table保存子问题的中间结果。(后面会有例子具体介绍)

和分治算法比较类似,但不同的是分治算法把原问题划归为几个相互独立的子问题,从而一一解决,而动态规划则是针对子问题有重叠的情况的一种解决方案。

目前design DP主要有两个思路:

一个是利用recursive method,即首先把问题用递归的方法解决,然后用一个table保存recursive中的中间结果,这不就避免了递归中重复计算的低效了吗?遇到需要计算以前计算过的东西,直接查表就OK,总之一句话,先写recursive,然后比葫芦画瓢基本就能把DP的方法写出来。这里的难点是如何找到recursive。算法导论里面也给的是这个思路。下面的前三个例子全部出自《算法导论》。

另一个思路是exhaust search,这个好像是我们老师发明的方法,这里有篇Kirk的论文, How to design dynamic programming algorithms sans recursion 有兴趣的大家可以仔细研究一下,我下面也会简单举例介绍一下这个方法。

下面的例子中多数代码都是伪代码,旨在illustrate idea。同时节省时间。代码中都省去了backtrack的过程,即只得到了optimal solution的值,省去了如何construct optimal solution的过程。这个一般用一个数组记录一下就OK了。

转载于:http://www.cnblogs.com/Gavin_Liu/archive/2011/04/13/2011214.html

先来个比较简单的例子(其实后面的也不难O(∩_∩)O~)

例:Rod-cutting problem(切木头问题。感觉翻译过来怎么就变了味呢?囧。。。)

Input:有一个长n米的木头,和一个price table,table如下:

长度 i 1  2  3  4  5  6 。。。

价格 Pi 1  5  8  9  10  17。。。

意思很明显,就是长度为1米的木头可以买1元,长5米的可以卖10元,依次类推

Output:找一个cut的方法,使最后赚的钱最多。

很显然,这个递归的主要思路是我切一刀之后,分成两段,一段我按table的价钱卖了,另一段我当成一个新的子问题,继续作为我的函数的新的参数,这样不就递归了吗?(__) 但是问题是这一刀怎么切,没错,我们就来个找最大值,即max_{i =1 to n} Pi + Cut(n-i).

所以,递归函数应该是:

Cut(P, n){ //P 就是我的table,n是木头长度
   
  if n == 0
      return 0;
  q = -infinity
  for i = 1 to n
      q = max(q,P[i]+Cut(P,n-i))
  return q;
  

}

然后,根据这个recursive写DP

Cut(P, n){

  for(int i = 1; i<=n; i++){

    q = -infinity;

    for(int j = 1; j<=i; j++)

      q = max(q, P[j] + r[i-j]);

    r[i] = q;

  }

  return r[n];

}

猜你喜欢

转载自blog.csdn.net/Eric_LH/article/details/83345912