完全背包
题目:有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。
第 i 种物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
完全背包问题,比起0-1背包更符合动态规划的一般方式,由前往后递推。
那么在之前的两个嵌套循环当中再添加一个循环用来表示加入 k 件 i 物品后的价值量与 i -1 的循环形成的价值量做比较,取最优。
for(int i = 1;i <= N;i ++)
for(int j = 1;j <= V;j ++)
for(int k = 0;k*v[i-1] <= j;k ++)
dp[i][j] = max(dp[i][j],dp[i-1][j-k*v[i-1]]+k*w[i-1]);
完整代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
/*
完全背包
每种物品可以选任意次,要求实现给定容积物品价值最大
*/
const int N = 4; //物品个数
const int V = 5; //背包容积
int w[N] = {2,4,4,5}; //物品价值
int v[N] = {1,2,3,4}; //物品体积
int knapsack(){
//dp[i][j]是考虑前i件物品并且体积为j时的价值量最优解
vector<vector<int> > dp(N+1,vector<int>(V+1)); //dp初始化
for(int i = 1;i <= N;i ++)
for(int j = 1;j <= V;j ++)
for(int k = 0;k*v[i-1] <= j;k ++) //在容积范围内放尽可能多的i物品与之前的价值量对比
dp[i][j] = max(dp[i][j],dp[i-1][j-k*v[i-1]]+k*w[i-1]);
//打印状态转移矩阵
for(int i = 1;i <= N;i ++){
for(int j = 1;j <= V;j ++) cout<<dp[i][j]<<" ";
cout<<endl;
}
//返回结果
return dp[N][V];
}
int main(){
cout<<knapsack();
}
运行结果: