参考链接:
01背包、完全背包、多重背包问题的C++实现
史上最易懂的01背包,完全背包,多重背包讲解
浅谈分组背包
各种背包的描述:
01背包(ZeroOnePack): 有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
完全背包(CompletePack): 有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
多重背包(MultiplePack): 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
分组背包有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
容量为10的背包,有5种物品,每种物品只有一个,其重量分别为5,4,3,2,1,其价值分别为1,2,3,4,5。
设计算法,实现背包内物品价值最大。
代码如下(输出14)
#include
#include
using namespace std;
int main()
{
int total_weight = 10;
int w[6] = { 0,5,4,3,2,1};
int v[6] = { 0,1,2,3,4,5};
int dp[11] = { 0 };
for (int i = 1; i <= 5; i++)
for (int j = 10; j >= w[i]; j--)
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
cout << "总的价值为: " << dp[10] << endl;
return 0;
}
容量为10的背包,有5种物品,每种物品数量无限,其重量分别为5,4,3,2,1,其价值分别为1,2,3,4,5。
设计算法,实现背包内物品价值最大。
代码如下(输出50)
#include
#include
using namespace std;
int main()
{
int total_weight = 10;
int w[6] = { 0,5,4,3,2,1};
int v[6] = { 0,1,2,3,4,5};
int dp[11] = { 0 };
for (int i = 1; i <= 5; i++)
for (int j = w[i]; j <= 10;j++)
dp[j] = max(dp[j],dp[j - w[i]] + v[i]);
cout << "总的价值为: " << dp[10] << endl;
return 0;
}
容量为10的背包,有5种物品,每种物品数量分别为1,2,1,2,1,其重量分别为5,4,3,2,1,其价值分别为1,2,3,4,5。
设计算法,实现背包内物品价值最大。
代码如下(输出16)
#include
#include
using namespace std;
int main()
{
int total_weight = 10;
int w[6] = { 0,5,4,3,2,1 };
int v[6] = { 0,1,2,3,4,5 };
int cot[6] = { 0,1,2,1,2,1 };
int dp[11] = { 0 };
for (int i = 1; i <= 5; i++)
for (int k = 1; k <= cot[i];k++)
for (int j = 10; j >= w[i]; j--)
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
cout << "总的价值为: " << dp[10] << endl;
return 0;
}
乍一看好像很难的样子,其实仔细想想很简单,这种问题完全可以用01背包解决。 对于分组背包,可以这样想:虽然分成很多组,但只能选一个,或者不选,这和01背包是一样的,也就是说,对于01背包里每一个独一无二的物品,对应的分组背包就是每一组中选择一个物品,这样来看,完全就是01背包问题。
下面是状态方程:
for(int i = 1; i <= z; i++)
for(int j = V; j >= 1; j--)
for(int k = 1; k <= n; k++)
dp[j] = max(dp[j - w[i][k]] + p[i][k], dp[j]);
其中,z是分组数,V是背包体积,n是每组物品数量,w和p分别是第i组第k个物品的体积和价值。
为什么要这样写呢?可以想一下01背包的状态方程,和这个外两层的循环是一样的,不一样的是里面又加了一层,这层循环是遍历每一组的物品用的,对于dp[]中每一个状态都是循环了一遍每一组的物品才换到下一个的,所以对后面的没有影响,也就保证了每组物品最多只有一件。