[笔记]动态规划与01背包问题


此笔记为个人学习记录,欢迎大佬指出误区,如有和你的认知矛盾之处,以你为准

关于动态规划

基本思想:避免重复计算

适用问题特征:重复子问题

如何实现:将原问题拆分为若干个更小的问题,通过dp数组存储子问题的结果,
(想象一个金字塔,先把最底层的盖完后,第二层就能在最底层的基础上再盖,以此类推),
在某个较大子问题包含已经求解过的子问题的时候,直接从dp数组中取得该结果,得出结果后再次存入dp数组,以避免该子问题的重复计算,
以此类推,当某个更大的子问题包含这个较大子问题时,同样可以直接从dp数组中再次取得结果,直到问题解决。

思考过程

显然动态规划的灵魂所在就是dp数组(Dynamic Programming)
所以首先得明确dp数组的下标(还有要使用一维还是更多维的数组)和其对应的子问题的含义
然后确定递推公式:即上述中子问题较大子问题更大的子问题之间是如何转换的(这一步一般是最难也是最关键的
之后将dp数组初始化,确定遍历顺序,找几个例子检验一下即可

01背包问题

概述

有N件物品和一个容量为W的背包。
每第i件物品的重量为weight[i],价值为value[i]。
每件物品仅有一件,可选择装与不装。
求解选择装入哪些物品时得到的价值最大。

思考过程

建立dp数组://存放子问题的结果

对dp[i][j]:
i:[0…i]号备选物品
注意这里是从0号到i号之间的所有物品
j:背包的容量上限
时刻注意dp[i][j]数组仅存放了一个数字,这个数字对应着条件为i和j时的最优解

递推公式推导://建立i与i-1之间的关系

首先固定背包容量为j,对每一个第i件物品有两种选择:
1>不放入这个第[i]件物品:
此时有 dp[i][j]=dp[i-1][j] //相当于不存在这一件物品(这一件物品不影响问题的最优解)
所以结果为0~i-1(没有第i件物品)时的最优解
2>放入这个第i件物品时:
dp[i][j]=+value[i]+dp[i-1][j-weight(i)] //优先处理这一件物品,获得价值value[i],同时背包容量减少这件物品的重量即[j-weight(i)]
此时背包大概率还是能装下一点别的东西的,这点剩下的容量能装下的价值就是dp[i-1][j-weight(i)](因为第i号物品已经在包里了,所以备选物品从0~i-1里选)

那么到底是装还是不装呢,只需要对上面两种情况带来的价值进行比较即可,于是得到递推公式
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

dp数组初始化

显然备选物品数量和背包容量不应该为负值,但是由递推公式可以预料到,i=0时,i-1就为负值,所以在i=0时,不应依照递推公式,而是应当自己手动对其进行赋值,以便后续的问题依次进行解决

对dp[0][j]:此时备选物品仅有第0号(也就是第一件,这里标为0只是为了对应数组规则)物品,此时对与容量为j的背包有两种可能:
当背包容量装不下第0号物品时,即j<weight(0)时,dp[0][j]=0;
当背包能装下第0号物品时,即j>=weight(0)时,dp[0][j]=value(0);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值