背包问题(0/1背包,完全背包,多重背包)

你的背包让我走得好缓慢,借了终于陪着我腐烂

1. 0/1背包

有一个腐烂的背包,容量为v,现有n件物品,每件物品有两个属性,体积w,和价格p,我们要选择物品往背包里放,使得在物品总容积不超过v的情况下价值最大。

思路:

1)我们只在乎某件物品放不放进背包,而不在乎放进去的顺序,因为物品一样,顺序不一样,结果相同。

2)我们从第一件物品开始考虑,只有两种情况,放或不放,然后考虑第二件物品,放或不放,。。。。。。第n件物品放或不放。

3)放则记为1,不放记为0.那么假如共4件物品,所有可能的情况为0000,0001,0010,0011.....1111共16种情况。只要枚举完这16种情况我们就知道最大价值是多少。

4)虽然上面说有16种情况,但实际上有些情况是不存在的,例如1111,放入第四个物品会超出背包容量,所以应为1110。

5)我们定义maxValue(n,v)为容量为v时,选取物品1~n中若干件所能得到的最大价值。我们从第n件到第1件物品依次判断是否选取,每步都有下面的公式。不选maxValue(n-1,v),选maxValue(n-1,v-Vn)+Pn,取max

                                          0                                    1

---maxValue(n,v)=max(maxValue(n-1,v), maxValue(n-1,v-Vn)+Pn),

当第k件物品遇到Vrest<Vk那么第k件物品只能不选取:

---maxValue(n,v)=maxValue(n-1,v)

这样在边界的时候我们是可以直接得出结果的,然后回溯得出maxValue(n,v)。

解法:

1)我们可以用递归函数来求,注意的是要用一个temp[n][v]数组存储已经求过的maxValue(n,v)来避免重复计算,因为到达状态[n,v]的可能不止一种情况。

2)用动态规划,递归是自顶向下,到达边界在回溯,而动态规划则是直接自底向上。

每个maxValue(n,v)关联的状态只有maxValue(n-1,v)或maxValue(n-1,v-Vn).所以我们我们填一个n+1行v+1列的表,从maxValue(0,0)一直到maxValue(n,v),一直迭代。详细解释见https://blog.csdn.net/qq_38410730/article/details/81667885

2. 完全背包

在完全背包中是不限制每件物品的数量的,而0/1背包是每种物品只有一件。此时的问题不是针对每种物品放或不放(放0个或1个),而是放几个的问题(放0个,1个,2个。。。。or n个),这里物品i最多放maxSpace//vi件。因此我们在放每件物品的时候要多加一个循环,分别算出maxValue(i,v)在物品i取0至maxSpace//vi件时的值,取最大的作为maxValue[i][v]的最终值。动态规划填表一行一行的填。详细见https://www.cnblogs.com/mfrank/p/10803417.html

3.多重背包

每种物品的数量为num[i]个,完全背包的物品数是无限的,多重背包是有限个。和完全背包基本相同,核心是每种物品放几个,从0~num[i], 个数不超过num[i]的同时空间也不能超过背包容量,详细见https://www.cnblogs.com/mfrank/p/10816837.html

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


int main(){
    int space,kind;
    cin>>space>>kind;
    vector<vector<int>>data(kind+1,vector<int>(3,0));
    vector<vector<int>>dp(kind+1,vector<int>(space+1,0));

    //space  price  num
    //注意这里是从1开始,只有物品1~kind,没有物品0
    for(int i=1;i<kind+1;i++)cin>>data[i][0]>>data[i][1]>>data[i][2];

    for(int i = 1; i<kind+1;i++){
        for(int j=1;j<space+1;j++){
            for(int k=0;k<=data[i][2]&&j>=k*data[i][0];k++){//0表示不选,注意选的第i件物品总体积不超过当前的容量
                //由于这里考虑的是选k件物品的数量,所有下面每次减掉的空间是k*data[i][0],增加的价值是k*data[i][1]
                    dp[i][j]=max(dp[i][j],dp[i-1][j-k*data[i][0]]+k*data[i][1]);
            }
        }
        

    return 0;
}











我不生产知识,我只是知识的搬运工------农夫

猜你喜欢

转载自blog.csdn.net/qq_41033241/article/details/105458125