01背包

本文介绍了一个经典的背包问题求解方法,通过动态规划算法实现。详细解释了如何利用二维数组dp[][]来存储每一步的最佳选择,并逐步优化到一维数组dp[]以减少空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述:

现有n个物体和容量为V的背包,每个物体i都有对应的重量w[i]和价值v[i],每个物体最多拿一次,在所取物体总重量不超过V的情况下,能获得的最大价值是多少?

分析

  • 每个物体只有拿和不拿两种情况,则在选择是否拿第i件时,在之前已确定部分的基础上进行比较判断即可
  • 申请一个二维数组dp[][],用dp[i][j]来表示在物品数量为i,总重量为j的条件下能达到的最大价值,那么dp[i][j]的值为:最后dp[n][V]即为答案

Code

1
2
3
4
5
6
7
8
for(int i=1;i<=n;i++)
for(int j=V;j>0;j--)
{
if(a[i]<=j)f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
else f[i][j]=f[i-1][j];
//f[i-1][j]没拿时的价值,f[i-1][j-a[i]]+b[i]拿了之后的价值
//i为前i个物体,j为剩余背包空间
}

优化

  • 前面的代码在时间复杂度上已经无法继续优化,但是在空间复杂度上,因为我们只需要最多取n个的答案,所以我们可以在dp[i][j]的基础上去掉物体数这一维,那么dp[j]的值就为:

Code

1
2
3
for(int i=1;i<=n;i++)
for(int j=V;j>=w[i];j--)
dp[j]=max(dp[j] , dp[j-w[i]]+v[i]);

注意

  • 在遍历重量的时候是V->w[i],并不是w[i]->V,其原因是:第i个物体的状态只与i-1有关,我们在操作dp[j]的时候必须保证dp[j-w[i]]是上一次操作后的结果,如果从w[i]->V,那么dp[j-w[i]]的值在操作dp[j]之前就已经发生了改变,里面存的不是i-1时刻的值
  • 数组dp的值要全部初始化为0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值