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背包问题,你该了解这些 滚动数组 416. 分割等和子集