1.01背包
山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。
最基础的一个背包,首先考虑状态转移,设dp[i][j]表示容量为j,放入前i个物品所得的最大价值
很明显,如果还有剩余的话,dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])。
然后考虑滚动数组压掉一维
很明显,当前状态只能从前一个状态转来,所以可以去掉i这一维。
dp[j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
#include<bits/stdc++.h>
using namespace std;
int t,m;
int w[100010],v[100010],f[100010];
int main(){
scanf("%d%d",&t,&m);
for(int i=1 ; i<=m ; i++) scanf("%d%d",&w[i],&v[i]);
for(int i=1 ; i<=m ; i++){
for(int j=t ; j>=w[i] ; j--){ //注意倒着循环
f[j] = max(f[j],f[j-w[i]]+v[i]);
}
}
printf("%d",f[t]);
return 0;
}
2.完全背包
山洞里有一些不同种类的草药,采每一种都需要一些时间,每一种也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。
此题和原题的不同点:
1. 每种草药可以无限制地疯狂采摘。
2. 药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!
很明显, 跟01背包不同的是,每种药有无数个
状态转移方程不变,只不过是j正着循环
#include<bits/stdc++.h>
using namespace std;
int t,m;
long long w[10000010],v[10000010],f[10000010];
int main(){
scanf("%d%d",&t,&m);
for(int i=1 ; i<=m ; i++) scanf("%lld%lld",&w[i],&v[i]);
for(int i=1 ; i<=m ; i++){
for(int j=w[i] ; j<=t ; j++){//正着循环
f[j] = max(f[j],f[j-w[i]]+v[i]);
}
}
printf("%lld",f[t]);
return 0;
}
3.多重背包
小 FF 有一个最大载重为 W 的采集车,洞穴里总共有 n 种宝物,每种宝物的价值为 vi,重量为 wi,每种宝物有 mi 件。小 FF 希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。
跟上面两种区别是每一个物品的数量不固定
然后考虑二进制,2^0+2^1+······+2^k ,能表示2^k+1-1的所有数
所以把物品根据二进制,分成重量为1,2,4,8······,把复杂度优化一个log
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48) ; ch=getchar();}
return x*f;
}
int n,x;
int sum,ans;
int dp[1000010];
int V[1000010],W[1000010];
int main(){
n=read();x=read();
for(register int i(1) ; i<=n ; i=-~i){
int v,w,m;
v=read();w=read();m=read();
for(register int j(1) ; j<=m ; j*=2){ //类似二进制
sum++;
V[sum] = v*j;
W[sum] = w*j;
m-=j;
}
sum++;
V[sum] = v*m;
W[sum] = w*m;
}
for(register int i(1) ; i<=sum ; i=-~i){
for(register int j(x) ; j>=W[i] ; --j){ //相当于01背包
dp[j] = max(dp[j],dp[j-W[i]]+V[i]);
}
}
printf("%d",dp[x]);
return 0;
}