01背包

Posted julyzqy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了01背包相关的知识,希望对你有一定的参考价值。

01背包问题求解思路

  ①、确认子问题和状态 
  01背包问题需要求解的就是,为了体积V的背包中物体总价值最大化,件物品中第件应该放入背包中吗?(其中每个物品最多只能放一件) 
  为此,我们定义一个二维数组,其中每个元素代表一个状态,即前个物体中若干个放入体积为背包中最大价值。数组为:,其中表示前件中若干个物品放入体积为的背包中的最大价值。 
  ②、初始状态 
  初始状态为和都为0,前者表示前0个物品(也就是空物品)无论装入多大的包中总价值都为0,后者表示体积为0的背包啥价值的物品都装不进去。 
  ③、转移函数

if (背包体积j小于物品i的体积)
    f[i][j] = f[i-1][j] //背包装不下第i个物体,目前只能靠前i-1个物体装包
else
    f[i][j] = max(f[i-1][j], f[i-1][j-Vi] + Wi)

用背包表理解一下:

技术图片

细心观察,这个表格的每行代表第几个物品,某列代表当前你的背包有多大的容量,f[i][j]就是对应的这个二维表

代码:

普通版代码
#include<bits/stdc++.h>//万能头文件
#define ll long long
using namespace std;
const ll maxn=100;
ll n,v,f[maxn][maxn];
ll c[maxn];//每个物品占用空间
ll w[maxn];//每个物品的价值
int main()
{
    cin>>n>>v;
    for(ll i=1;i<=n;i++)
        scanf("%lld",&c[i]);
    for(ll i=1;i<=n;i++)
        scanf("%lld",&w[i]);
    for(ll i=1;i<=n;i++)//第i个物品
        for(ll j=v;j>=0;j--)//剩余空间j
        {
            if(j >= c[i])//如果装得下
                    f[i][j]=max( f[i-1][j-c[i]]+w[i],f[i-1][j]);
            else//如果装不下
                f[i][j]=f[i-1][j];
        }
    cout<<f[n][v]<<endl;//输出答案

}
空间优化版代码
#include<bits/stdc++.h>//万能头文件
#define ll long long
using namespace std;
const ll maxn=100;
ll n,v,f[maxn];
ll c[maxn];//每个物品占用空间
ll w[maxn];//每个物品的价值

int main()
{
    cin>>n>>v;
    for(ll i=1;i<=n;i++)
        scanf("%lld",&c[i]);
    for(ll i=1;i<=n;i++)
        scanf("%lld",&w[i]);
    for(ll i=1;i<=n;i++)//第i个物品
        for(ll j=v;j>=1;j--)//剩余空间j
        {
            if(f[j]<=f[j-c[i]]+w[i] && j-c[i]>=0 )//二维数组变一维数组
                 f[j]=f[j-c[i]]+w[i];//如果值得改变并且j的空间还装得下就赋新值
        }
    cout<<f[v]<<endl;//输出答案

}

 

 

 

 

以上是关于01背包的主要内容,如果未能解决你的问题,请参考以下文章

01背包问题模板代码

代码随想录算法训练营第四十二天 | 01背包问题,你该了解这些01背包问题,你该了解这些 滚动数组 416. 分割等和子集

把01背包问题的底裤扒个底朝天!!!

0-1背包问题的回溯法中,剪枝用的上界函数问题

用回溯法求01背包问题,怎样使用C++模板啊,迫切求指点!

01背包模板全然背包 and 多重背包(模板)