01背包、完全背包、多重背包、分组背包

参考链接:

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]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

01背包问题

容量为10的背包,有5种物品,每种物品只有一个,其重量分别为5,4,3,2,1,其价值分别为1,2,3,4,5。 
设计算法,实现背包内物品价值最大。 
代码如下(输出14)

#include <iostream>
#include<algorithm>

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 <iostream>
#include<algorithm>

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 <iostream>
#include<algorithm>

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[]中每一个状态都是循环了一遍每一组的物品才换到下一个的,所以对后面的没有影响,也就保证了每组物品最多只有一件。

猜你喜欢

转载自blog.csdn.net/aaakkk_1996/article/details/81744530