【C++ 动态规划-01背包问题,一篇就够了】

01背包-题目

01背包的经典问题是:

一个小偷拿着一个容量有限(容量设为w)的背包去商店偷东西,每个商品都有自己的体积v和价值c,并且每个商品只有一件。小偷的目的就是用这个容量有限的背包装满价值总量最大的东西。 现在给出n件商品的体积 𝑣𝑖 (i从1到n) 和价值 𝑐𝑖(从1到n)以及背包的容量w,请求出在这n件商品中用一个容量为w的背包能够拿到的商品的最大价值是多少?

01背包的特点是:每种物品仅有一件,可以选择拿或不拿

那么,他的状态转移方程是什么呢?(动态规划·入门(最长上升子序列,初级) 请点我!

请注意,这体用贪心方法是不能AC的,因为如果两个物品的价值加起来大于当前最大的物品价值 ,用贪心的方法做就会WA,并且,有两种情况:一种是因为背包装不下了所以不拿;而另一种就是不拿比拿更划算。

我们可以将dp[ i ][ j ]看作前 i 种物品的体积是 j

那么拿的话,i种物品(种类)就要-1,背包容积就要减去当前物品的体积,那么完整的就是:

if(j<v[i])
{
     dp[i][j]=dp[i-1][j];
}
else
{
      dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+c[i]);
}

需要注意,01背包需要逆序求解,所以完整代码是:

#include<bits/stdc++.h>
using namespace std;
int c[25],v[25],dp[25][105],n,w;
int main()
{
    cin>>n>>w;
    for(int i=1;i<=n;i++)
    {
        cin>>c[i];
    }
    for(int i=1;i<=n;i++)
    {
        cin>>v[i];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=w;j>=1;j--)
        {
            if(j<v[i])
            {
                dp[i][j]=dp[i-1][j];
            }
            else
            {
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+c[i]);
            }
        }
    }
    cout<<dp[n][w];
    return 0;
}

但是,我们需要优化空间,该怎么做呢?

我们知道,如果拿不了的话,当前状态和上一个状态是一样的,所以dp[i][j]中的i可以省略!

那么就改为:

​
#include<bits/stdc++.h>
using namespace std;
int c[25],v[25],dp[105],n,w;
int main()
{
    cin>>n>>w;
    for(int i=1;i<=n;i++)
    {
        cin>>c[i];
    }
    for(int i=1;i<=n;i++)
    {
        cin>>v[i];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=w;j>=1;j--)
        {
            if(j<v[i])
            {
                dp[j]=dp[j];
            }
            else
            {
                dp[j]=max(dp[j],dp[j-v[i]]+c[i]);
            }
        }
    }
    cout<<dp[w];
    return 0;
}

​

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值