背包问题
主要大纲来自于 崔添翼 (Tianyi Cui)《背包九讲》,本博客主要为代码实现及一些小思路。此外,代码中变量名会尽量统一,可能与原题给出变量名误差较大。
一、01 背包问题
代码相关题目:P1048 [NOIP2005 普及组] 采药
空间:O(VN)
时间:O(VN)
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,v;
int c[N],w[N];
int f[N][N];
int main(){
scanf("%d%d",&v,&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&c[i],&w[i]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=v;j++){
f[i][j]=f[i-1][j];
if(c[i]<=j) f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]);
}
}
printf("%d",f[n][v]);
return 0;
}
空间:O(V)
时间:O(VN)
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,v,c[N],w[N],f[N];
void zero_one_pack(int f[],int ci,int wi){
for(int j=v;j>=ci;j--) //一定要逆序
f[j]=max(f[j],f[j-ci]+wi);
}
int main(){
scanf("%d%d",&v,&n);
for(int i=1;i<=n;i++) scanf("%d%d",&c[i],&w[i]);
for(int i=1;i<=n;i++) zero_one_pack(f,c[i],w[i]);
printf("%d",f[v]);
return 0;
}
可测试数据,发现答案为100
100 3
99 100
50 20
50 30
如果题目中强调要装满背包 (背了不嫌重咩,强迫症福音)
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
const int FINF=-0x3f3f3f3f;
int n,v;
int c[N],w[N];
int f[N];
int main(){
scanf("%d%d",&v,&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&c[i],&w[i]);
}
memset(f,FINF,sizeof(f)); //赋值为负无穷
f[0]=0; //唯一满足满背包合法解的“0背包”
for(int i=1;i<=n;i++){
for(int j=v;j>=c[i];j--){
f[j]=