动态规划-背包问题入门-01背包

动态规划的背包问题是一类经典的组合优化问题,通常包括 0-1 背包问题、完全背包问题和多重背包问题。我们今天先从01背包做这个专项的入门。

01背包是所有背包问题的基础,它的大致模型为

有一个体积为V的背包,商店有n个物品,每个物品有一个价值v和体积w,每个物品只能被拿一次,问能够装下物品的最大价值。

这里每一种物品只有两种状态即"拿"或"不拿"。

设状态dp[i] [j]表示第i个物品为止,拿的物品总体积j的情况下的最大价值。

我们并不关心某个物品有没有被拿,只关心当前体积下的最大价值。

转移方程为:dp[ i] [j] = max(dp[ i - 1] [ j],dp[i - 1] [j - w] + v );如果不拿物品i,那么最大价值就是dp[i- 1 ] [j],如果拿了就是从体积j -v转移过来,体积会变大w,增加v。

最后输出dp[n] [V];

这里有一个01背包的大致模板

#include <iostream>
using namespace std;
using ll =long long ;
const int N = 105,M = 1050;
ll dp[N][M];
int main()
{
 int n,V;cin>>n>>V;
for(int i = 1 ;i<=n;i++)
{
   ll w,v;cin>>w>>v;
   for(int j = 0;j<=V;j++)
   {
     if(j>=w)dp[i][j] = max(dp[i -1 ][j],dp[i-1][j - w] + v);
     else dp[i][j] = dp[i -1][j];
   }
}
cout<< dp[n][V] << endl;
  return 0;
}

为了加深对01背包思想的深刻理解,我们通过一道例题来加深印象,这个题目大致意思为

小明有一个容量为 V 的背包。

这天他去商场购物,商场一共有 N 件物品,第 i 件物品的体积为 wi​,价值为 vi​。

小明想知道在购买的物品总体积不超过 VV 的情况下所能获得的最大价值为多少,请你帮他算算。

这个题目就是经典01背包的板子题,可以完全套用上述模板,

具体思路为:

  1. 定义一个二维数组dp,dp[i][j]表示在前i个物品中选择,且总体积不超过j的情况下所能获得的最大价值。

  2. 初始化边界条件:当物品数量为0或背包容量为0时,dp[i][j]均为0。

  3. 对于每一个物品i,根据其体积和价值有两种选择:
    a. 如果当前物品的体积大于背包容量j,则不能放入背包,保持上一行的价值不变:dp[i][j] = dp[i-1][j]。
    b. 如果当前物品的体积小于等于背包容量j,则可以选择放入背包或不放入背包:

    • 如果选择放入背包,则当前价值等于上一个物品的价值加上剩余背包容量为j-weight[i]时的最大价值:dp[i][j] = dp[i-1][j-weight[i]] + value[i]。
    • 如果选择不放入背包,则当前价值等于上一个物品时的最大价值:dp[i][j] = dp[i-1][j]。
      选择放入背包或不放入背包时,取其最大值,即 dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i])。
  4. 最终,dp[N][V]即为所能获得的最大价值,N为物品的总数量,V为背包的容量。

其他01背包相关的题目都可以套用这个思路。

接下来,就会讲解多重背包和完全背包,这些都是基于01背包的,所以大家还是对01背包熟练掌握,这样学其他背包问题的时候才能得心应手。

原01背包板子题链接:

https://www.lanqiao.cn/problems/1174/learning/?page=1&first_category_id=1&name=%E5%B0%8F%E6%98%8E%E7%9A%84%E8%83%8C%E5%8C%851

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值