背包问题
01背包问题
https://www.acwing.com/problem/content/2/
f[i] [j]里面是在前i个物品里面 选取不超过j的最大的总价值
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) {
cin>>v[i]>>w[i];
}
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
if(v[i]<=j) f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
}
}
cout<<f[n][m];
return 0;
}
优化
完全背包问题
https://www.acwing.com/problem/content/3/
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
if(v[i]<=j) f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]);
}
}
cout<<f[n][m]<<endl;
}
多重背包
https://www.acwing.com/video/325/
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n,m;
int v[N],w[N],s[N];
int f[N][N];
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>v[i]>>w[i]>>s[i];
for(int i=1; i<=n; i++) {
for(int j=0; j<=m; j++) {
f[i][j]=f[i-1][j];
for(int k=1; k<=s[i]; k++) {
if(v[i]*k<=j) f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k);
}
}
}
cout<<f[n][m]<<endl;
}
优化
https://www.acwing.com/activity/content/problem/content/1000/
将多重背包问题转化为01背包问题,按照二进制进行拆分
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
struct Good{
int v,w;
};
int n,m;
int f[N];
int main(){
cin>>n>>m;
vector<Good> goods;
for(int i=1;i<=n;i++){
int v,w,s;
cin>>v>>w>>s;
for(int k=1;k<=s;k*=2){
s-=k;
goods.push_back({v*k,w*k});
}
if(s) goods.push_back({v*s,w*s});
}
for(auto good:goods){
for(int j=m;j>=good.v;j--){
f[j]=max(f[j],f[j-good.v]+good.w);
}
}
cout<<f[m]<<endl;
return 0;
}
分组背包问题
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int f[N],v[N],w[N];
int n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
int x;
cin>>x;
for(int i=1;i<=x;i++) cin>>v[i]>>w[i];
for(int i=m;i>=0;i--){
for(int j=1;j<=x;j++){
if(v[j]<=i) f[i]=max(f[i],f[i-v[j]]+w[j]);
}
}
}
cout<<f[m]<<endl;
return 0;
}