01背包问题,完全背包问题,多重背包问题C++实现
- 01背包问题:
有 N 件物品和一个容量为 V 的背包。放入第 i 件物品耗费的费用是 Ci1,得到的
价值是 Wi。求解将哪些物品装入背包可使价值总和最大。
- 完全背包问题:
有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用。放入第 i 种物品
的费用是 Ci,价值是 Wi。求解:将哪些物品装入背包,可使这些物品的耗费的费用总
和不超过背包容量,且价值总和最大。
- 多重背包问题:
有 N 种物品和一个容量为 V 的背包。第 i 种物品最多有 Mi 件可用,每件耗费的
空间是 Ci,价值是 Wi。求解将哪些物品装入背包可使这些物品的耗费的空间总和不超
过背包容量,且价值总和最大。
基于《背包问题九讲 2.0 beta1.2》实现
参考:动态规划之背包问题系列 - SMON的文章 - 知乎
0-1背包问题的动态规划算法 - Bat特白的文章 - 知乎
非常感谢各位的博客解答,如果大家看完后有不理解的可以参考代码,也可以自己进行实现,这样才能更深刻的理解。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 01背包问题
int zeroOnePack(int V,vector<int> w,vector<int> c){
vector<vector<int>> dp(w.size()+1,vector<int>(V+1,0));
// 使用二维数组
for(int i=1;i<5+1;++i){
for(int j=1;j<V+1;++j){
if(c[i-1] > j){
dp[i][j] = dp[i-1][j];
} else{
dp[i][j] = max(dp[i-1][j],w[i-1]+dp[i-1][j-c[i-1]]);
}
}
}
return dp[w.size()][V];
}
// 01背包问题优化
void zeroOnePackCore(vector<int> &F,int c,int w,int V){
for(int v=V;v>=c;v--){
F[v] = max(F[v],F[v-c] + w);
}
}
int zeroOnePackOptimize(int V,vector<int> w,vector<int> c){
// 使用一维数组
vector<int> dp2(V+1,0);
for(int i=1;i<w.size()+1;i++){
zeroOnePackCore(dp2,c[i-1],w[i-1],V);
}
return dp2[V];
}
// 完全背包问题
int completePack(int V,vector<int> w,vector<int> c){
vector<vector<int>> dp(w.size()+1,vector<int>(V+1,0));
for(int i=1;i<5+1;++i){
for(int j=1;j<V+1;++j){
if(c[i-1] > j){
dp[i][j] = dp[i-1][j];
} else{
dp[i][j] = max(dp[i-1][j],w[i-1]+dp[i][j-c[i-1]]);
}
}
}
return dp[w.size()][V];
}
// 完全背包问题优化
void completePackCore(vector<int> &F,int c,int w,int V){
for(int v=c;v<=V;v++){
F[v] = max(F[v],F[v-c] + w);
}
}
int completePackOptimize(int V,vector<int> w,vector<int> c){
vector<int> dp(V+1,0);
for(int i=1;i<w.size()+1;i++)
completePackCore(dp,c[i-1],w[i-1],V);
return dp[V];
}
// 多重背包问题
int multiplePack(int V,vector<int> w,vector<int> c,vector<int> M){
vector<int> dp(V+1,0);
for(int i=1;i<w.size()+1;i++){
for(int j=V;j>=c[i-1];j--){
for(int k=0;k<=min(M[i-1],j/c[i-1]);k++)
dp[j] = max(dp[j],dp[j-k*c[i-1]]+k*w[i-1]);
}
}
return dp[V];
}
// 多重背包问题优化
void multiplePackCore(vector<int> &F,int c,int w,int m,int V){
if(c * m >= V){
completePackCore(F,c,w,V);
return;
}
int k = 1;
while(k < m){
zeroOnePackCore(F,c*k,w*k,V);
m = m - k;
k = k * 2;
}
zeroOnePackCore(F,c*m,w*m,V);
}
int multiplePackOptimize(int V,vector<int> w,vector<int> c,vector<int> M){
vector<int> dp(V+1,0);
for(int i=1;i<w.size()+1;i++){
multiplePackCore(dp,c[i-1],w[i-1],M[i-1],V);
}
return dp[V];
}
int main(){
int N = 5;
vector<int> w{1,6,18,22,28}; // 价值worth
vector<int> c{1,2,5,6,7}; // 耗费(重量)cost
vector<int> M{0,2,1,1,1}; // 多重背包中的数量number
int V; // 背包容量Volume
cin>>V;
cout<<"01背包问题的答案为:"<<endl;
cout<<zeroOnePack(V,w,c)<<endl;
cout<<zeroOnePackOptimize(V,w,c)<<endl;
cout<<"完全背包问题的答案是:"<<endl;
cout<<completePack(V,w,c)<<endl;
cout<<completePackOptimize(V,w,c)<<endl;
cout<<"多重背包问题的答案是:"<<endl;
cout<<multiplePack(V,w,c,M)<<endl;
cout<<multiplePackOptimize(V,w,c,M)<<endl;
return 0;
}
运行结果: