DP动态规划

DP动态规划的本质就是:求出规模为n的问题所需要的所有小规模问题的解,然后把该问题分解成两个小规模问题(考虑所有分解的情况),根据之前得到的解再加上小规模问题合并的代价得到这一种分解的答案,综合考虑所有的分解答案,取最优解

遍历并先后求解规模为i的问题,其中i=1~N

比如先求出规模为1的问题,再去求规模为2的问题(利用已有的规模为1的问题的答案),然后去求规模为3的问题(利用已有的规模为1和2的问题的答案)…最后求出规模为N的问题

遍历规模为i的问题里的每一种不同的情况

这句话有两个含义:

  • 遍历规模为i的问题时,要考虑所有规模为i的问题是否一样
  • 要考虑规模为i的问题,把它分解为更小规模问题的所有分法

首先,遍历规模为i的问题时,要考虑所有规模为i的问题是否是一样的?如果是不一样的,那么就要把所有规模为i的问题的解都求出来(用二维数组存储);如果是一样的,那求出一个就行了(用一维数组存储),举个例子:

规模为i的问题是一样的(一维数组存储小规模问题结果)

对于长度为n的钢条切割问题,切割成不同长度的售价是不同的,求最高的售价

根据dp的思想,我们先求出规模为1的问题,也就是先求长度为1的钢条切割问题,很显然它并不用切割,而且所有长度为1的钢条的价格都是一样的,我们把它存到一维数组price[1]中

然后再去求规模为2的问题,也就是求长度为2的钢条切割问题,有两种方案:不切 or 在中间切一刀,我们比较这两种方案取出售价最高的那一种存放到一维数组price[2]中

再去求解规模为3的问题,也就是求长度为3的钢条切割问题,可以是:不切 or 切成1+2 or 切成2+1(这个问题中,后面两种情况是一样的,但有些问题中可能是不一样的,比如切在不同位置的价格不同,也就是两个小规模问题的合并需要额外代价的情况),同样把最优解存在price[3]

最后我们再去求解规模为n的问题,也就是我们的目标,可以是:不切 or 切成1+(n-1) or 切成2+(n-2) or … or 切成(n-1)+1,所有的情况所分成的两个小规模的问题我们都已经求得最优解,因此只需要把它们作比较并求出售价最高的那一种作为最终的答案price[n]

思考一下,我们是通过小规模的问题来求解大问题的,因此我们要做的第一步是,先把规模为i的大问题分解成小问题,搞清楚递归过程是如何使用小问题的(可能是分解成两个小问题,也可能是多个),这一步的目的并不是要求解大问题,而是观察我们到底是要什么样子的小问题,然后再根据这个提示,去从头开始求解规模为1的小问题,规模为2的小问题…

可能你还不是很理解这段话的含义,下面我再举几个例子,让你更深刻地理解,做dp之前先搞清楚要如何使用小规模问题、要什么样的小规模问题这件事情有多么重要

规模为i的问题是不一样的(二维数组存储小规模问题结果)

对于多个矩阵连乘问题,不同的乘法顺序得到的计算量是不同的,求最小的运算量

注:矩阵相乘没有交换律,但是可以有结合律,也就是每个矩阵的相对位置不能变,但是相邻的矩阵哪两个先乘是可以变的

同样根据dp的思想,我们先求出规模为1的问题,也就是单个矩阵相乘的运算量,都是0

然后求规模为2的问题,也就是两个矩阵相乘的运算量,注意,把每两个相邻矩阵分为一组,它们相乘的计算量都是不同的!!!也就是说,对矩阵相乘来说,规模为2的问题得到的结果各不相同(对比钢条切割,所有长度为2的钢条切割都是一样的),我们需要求出所有规模为2的问题的运算量并保存下来,怎么保存呢?用二维数组,a[i][j],其中i表示第i个矩阵,j表示第j个矩阵,这样就可以很方便的保存任意规模的所有问题的解(只要i和j分别表示该问题的开头和结尾即可,a[i][i]就表示单个矩阵的小问题,值为0)

因此我们求出了a[1][2],a[2][3],…,a[n-1][n]

接下来求解规模为3的问题,同理,不同的三个相邻矩阵的小规模问题的解也是不同的,比如第6、7、8这三个矩阵,它可以被分解为a[6][7]和a[8][8],以及a[6][6]和a[7][8],也就是分解为规模为1的小问题和规模为2的小问题,当然,还有这两个小规模问题合并的代价(相当于两个矩阵相乘),我们把解存在a[i][i+2]上

最后求规模为n的问题,分解为a[1][1]和a[1][n]相乘、a[1][2]和a[2][n]相乘、…、a[n-1]和a[n]相乘

你会发现,矩阵相乘的dp问题,与钢条分割的问题不同之处在于,所有规模为i的问题都各不相同,需要用二维数组a[i][j]存储结果,并且用小规模问题求解大规模问题时还需要考虑问题合并的代价

因此,我们要先考虑规模为n的问题,它要的是不同的规模为i的问题,因此我们要把所有规模为i的问题都保存下来

0-1背包问题

参考知乎:https://zhuanlan.zhihu.com/p/30959069

假设我们有一个容量为W的背包,有n个价值为 v i v_i vi,体积为 w i w_i wi的物品,求如何从n个物品中挑选,才能在总体积不超过背包容量W的前提下,得到最大的总价值

同样我们把问题分解为更小规模的问题,但注意,这里需要分解的参数有两个,分别是第i个物品和容量限制w,当然一开始可能想的没那么清楚,我们像之前说的那样,从递归关系中去查看我们要如何分解、使用小问题,分析如下:

定义子问题P(i, W)为:在前i个物品中挑选总重量不超过W的物品,每种物品至多只能挑选1个,使得总价值最大;这时的最优值记作m(i, W),其中1<=i<=n, 1<=W<=C考虑第i个物品,无外乎两种可能:选,或者不选。

  • 不选的话,背包的容量不变,改变为问题P(i-1,W)
  • 选的话,背包的容量变小,改变为问题P(i-1,W-w_i)

最优方案就是比较这两种方案,哪个会更好些:

也就是说,解决规模为i的问题,我们先要有 P ( i − 1 , W ) P(i-1, W) P(i1,W) P ( i − 1 , W − w i ) P(i-1, W-w_i) P(i1,Wwi),由于也就是第i-1个物体放到某个容量的背包里的最大价值,因此一开始的小规模问题中,我们就要遍历并保存所有第i个物体放到从1~W(所有可能的背包残余容量)的背包中的最大价值,因此也用一个二维数组m[i][w]来保存结果

img

代码说明

一般在外面套一个for(i=1; i<=n; i++),i表示遍历的每一个规模的问题,在第i个循环中对第i个问题求解,如果需要保存二维数组的结果(规模为i的问题各不相同),那就再套一个循环,以求出规模为i的问题的所有情况的解,来供后面更大规模的问题使用

举例:PTA: Programming Contest

Bob will participate in a programming contest. There are altogether n problems in the contest. Unlike in PAT (Programming Ability Test), in a programming contest one can not obtain partial scores. For problem i, Bob will need time[i] to solve it and obtains the corresponding score[i], or he may choose not to solve it at all. Bob will be happy when he obtains a total score no less than happy_score. You are supposed to find the minimum time needed for Bob to be happy. The function need_time must return the minimum time, or -1 if it is impossible for Bob to obtain a score no less than happy_score.

Here n (1≤nMAXN) is the number of problems; happy_score (1≤ happy_scoreMAXS) is the minimum score for Bob to be happy; time[] is the array to store time[i] (1≤time[i]≤100) which is the time to solve problem i; score[] is the array to store score[i] (1≤score[i]≤100) which is the score Bob gets for solving problem i.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值