动态规划-入门

什么是动态规划,我们需要如何描述它?

  动态规划算法通常基于一个递推公式以及一个或多个初始状态。当前子问题的解将依赖上一子问题的解。使用动态规划来解决问题只需要多项式复杂度,因此它比回溯法,暴力法等要快许多。
首先,我们要招到某个状态的最优解,然后在它的帮助下,找到下一个状态的最优解。

“状态”代表什么以及如何找到它?

  “状态”用来描述该问题的子问题的解。如果我们有面值为 1 元、3元和 5 元的硬币若干枚,如何用最少的硬币凑够11元? (表面上这道题可以用贪心算法,但贪心算法无法保证可以求出解,比如1元换成2元的时候)
  首先我们思考一个问题,如何用最少的硬币凑够 i (i<11)?为什么要这么问呢? 两个原因:1.当我们遇到一个大问题时,总是习惯把问题的规模变小,这样便于分析讨论。 2.这个规模变小后的问题和原来的问题是同质的,除了规模变小,其它的都是一样的, 本质上它还是同一个问题(规模变小后的问题其实是原问题的子问题)。从最小的开始。当 i=0 ,我们需要多少硬币来凑够0元,由于1,3,5都大于0,即没有比0小的币值,因此凑够0元我们最少需要0个硬币。为了方便,使用数学标记 d(0)=0 来表示凑够0元我们最少需要0个硬币。则 d(i)=j 表示凑够 i 元需要最少j个硬币。当 i=1 时,只有面值为1的硬币可用,因此我们取面值为1的硬币,接下来只需要再凑够0元即可。所以我没有 d(1)=d(11)+1=0+1 ,当 i=2 时,仍然只有面值为1的硬币可以使用,取面值为1的硬币,接下来只需要再凑够 21=1 元即可,而这个答案已经知道,即 d(1) 。所以我没有 d(2)=d(21)+1=d(1)+1=2 。到目前为止,我们只有面值为1的硬币可以使用,操作起来非常简单。接下来我们需要凑够面值为 i=3 ,此时有面值为3和面值为1的硬币可供使用。既然能用的硬币有两种,我们就有两种方案。如果取一个1元硬币,我们的目标就变为:凑够 31=2 元需要的最少硬币数量。即 d(3)=d(31)+1=d(2)+1=2+1=3 。这个方案是直接取3个1元硬币。第二种方案,是我们可以取3元硬币。此时我们的目标就变成凑够 33=0 需要的最小硬币数,即 d(3)=d(33)+1=1 。很显然为了凑够3元,我们最优的方案为 d(3)=min{d(31)+1,d(33)+1}
  从以上文字,我们要抽象出动态规划两个重要的概念:状态和状态转移方程。上文中提到的 d(i) 即为我们的状态。在此我们如何选取状态?可以根据子问题来选取状态。即找到子问题,状态也就出来了。例如上面的文字,我们每次都在寻找 d(i) 。则 d(i) 就可当成我们的状态。既然我们用 d(i) 表示状态,那么状态转移方程自然包含d(i), 上文中包含状态d(i)的方程是: d(3)=min{d(31)+1,d(33)+1} 。没错, 它就是状态转移方程,描述状态之间是如何转移的。当然,我们要对它抽象一下,
d(i)=min{d(ivj)+1} ,其中 ivj>=0 vj 表示第 j 个硬币的面值;

pseudocode
set Min[i] equal to  Infinity for all of i
for i = 1 to S
    for j = 0 to N-1
        If (v[j] <= i & Min[i - v[j]] + 1 < Min[i])
            Min[i] = Min[i - v[j] + 1
Output min[S]

动态规划解。

  从上图可以得出,要凑够11元至少需要3枚硬币。通过追踪我们是如何从前一个状态值得到当前状态值的, 可以找到每一次我们用的是什么面值的硬币。比如,从上面的图我们可以看出, 最终结果d(11)=d(10)+1(面值为1),而 d(10)=d(5)+1 (面值为5),最后 d(5)=d(0)+1 (面值为5)。所以我们凑够11元最少需要的3枚硬币是:1元、5元、5元。
转载自

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值