动态规划常见类型

题目一:01背包问题

一个背包总容量为V,现在有N个物品,第i个 物品体积为weight[i],价值为value[i],现在往背包里面装东西,怎么装能使背包的内物品价值最大?

例题:给定一个数m,将m拆成不同的自然数的和的形式有多少种方案,这就是典型的01背包问题,背包容量为m,物品件数为k,这里面的k是隐含条件,可以求出来,因为m最多由1+2+…+k得到,由此可以根据m求得物品件数的上限。

题目二:完全背包问题

一个背包总容量为V,现在有N个物品,第i个 物品体积为weight[i],价值为value[i],每个物品都有无限多件,现在往背包里面装东西,怎么装能使背包的内物品价值最大?

例题:假设现在有1元、2元、5元的纸币很多张,现在需要20块钱,你能给多少种找钱方案,这就可以认为是完全背包问题,即背包容量为20,物品体积分别为1、2、5。

题目三:最少硬币找零问题

给予不同面值的硬币若干种种(每种硬币个数无限多),如何用若干种硬币组合为某种面额的钱,使硬币的的个数最少?

在现实生活中,我们往往使用的是贪心算法,比如找零时需要13元,我们先找10元,再找2元,再找1元。如果我们的零钱可用的有1、2、5、9、10。我们找零18元时,贪心算法的策略是:10+5+2+1,四种,但是明明可以用两个9元的啊。这种问题一般使用动态规划来解决。

一、首先来看01背包问题

用一个数组f[i][j]表示,在只有i个物品,容量为j的情况下背包问题的最优解。第i个物品可以选择放进背包或者不放进背包(这也就是0和1),假设放进背包(前提是放得下),那么f[i][j]=f[i-1][j-weight[i]+value[i];如果不放进背包,那么f[i][j]=f[i-1][j]。

这就得出了状态转移方程: 

  f[i][j]=max(f[i-1][j],f[i-1][j-weight[i]+value[i])  

二、完全背包问题 和 硬币找零问题
其实这个两个问题非常相似,都是物品数目无限多,一个是不超过某个重量值W求最大value,一个是要获得某个value,求最小重量(每个硬币可以看成是重量为1的物品)。

(1)对于完全背包问题状态转移方程: 

  f[ i ] [ j ] = max( f[i-1][j],  f[ i ][ j- weight[i] ] + value[i] )   ,注意后面是f[i, j-weight[i]],i 没有减1  

可以理解为:j为背包可以容纳的重量,有i种物品时,对于第i种物品,要么取或者不取,至于取多少个我们并不关心。

(2)对于硬币找零问题状态转移方程: 

  f[i][j]=min( f[i-1][ j ], f [i ] [ j - value[i] ] + 1)   ,注意后面是f[i, j-value[i]],i 没有减1  

可以理解为:j为需要找零多少元,有i种硬币,找零时对于第i种硬币,我们只考虑取或者不取,至于取多少个我们并不关心!

两种边界情况说明一下:
(1)f[0][j]=Integer.MAXVALUE ,因为 对金额为 j 的钱找零,但是可以的硬币面值种类为0,这显然是无法做到的。其实这是一个”未定义“的状态。它之所以初始为Integer.MAXVALUE
(2)f[i][0]=0,因为,对金额为0的钱找零,可用来找零的硬币种类有 i 种,金额为0怎么找啊,故设置为0。

转载于:https://www.cnblogs.com/nju-lfk/p/8719385.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值