“特殊”0-1揹包问题

引言

对于通常的0-1揹包问题来说,只用考虑重量以及放与不放这两个因素,今天看到一道问题加入了对于体积因素的考虑,即最终结果要求重量体积都不大于要求的值,且价值最大。
原题如下:
小刘去春游,有5个物品,已知各物品的质量、体积、个数、价格(各项数值可以自己找一组带一下,思想都是一样的),总共能带500cm³和100kg的物品,求能带物品的最大价值。请用递归算法解决。

递归解法

很明显这是在经典的0-1揹包问题上加了个干扰条件,其实如果真的完全了解0-1揹包的话就会发现其实本质都是一样的,不过是填格子,做选择,最后组合成找出最优解而已。
经典的0-1揹包递归式子k如下所示:

假设c[i,w]代表揹包中物品为i个且揹包承载重量为w时的最大价值。那么对于每一个物品,是否要放入揹包就可以写作如下递归式子:(vi表示当前物品价值)


c[i,w] = c[i-1][w] > c[i-1][w-wi]+vi ?c[i-1][w]:c[i-1][w-wi]+vi;

那么现在加入一个体积因素这个式子就可以写成:

假设c[i,w,v]代表揹包中物品为i个且揹包承载重量为w,体积为v时的最大价值。那么对于每一个物品,是否要放入揹包就可以写作如下递归式子:(bi表示当前物品价值)
c[i,w,v] = c[i-1][w][v] > c[i-1][w-wi][v-vi]+bi ?c[i-1][w][v]:c[i-1][w-wi][v-vi]+bi;

ok,既然递推式子出来了,那么递推函数代码也就呼之欲出了。在此以java举例

public class Main{
 static int W = 100;
 static int number = 5;
 static int V = 500;
 static int VALUE[] = {60, 20, 10, 60, 100};
 static int WEIGHT[] = {20, 30, 50, 60, 80};
 static int CAPACITY[] = {68,100,200,30,340};
 public static void main(String[] args)
 {
        int maxValue = calculate(number-1, W,V);
        System.out.println(maxValue);
 }
public static int calculate(int i, int j , int k)
{
        int r1 = 0;
        int r2 = 0;
        int r = 0;

        if (i == -1)
        {
                return 0;
        }

        if(j >= WEIGHT[i] && k >= CAPACITY[i])
        {
                r1 = calculate(i-1,j - WEIGHT[i],k-CAPACITY[i]) + VALUE[i];
                r2 = calculate(i-1,j,k);
                r = (r1>r2)?r1:r2;
        }

        return r;
}

}

从递归角度看,其实和经典0-1揹包差不多,无非是在递归判断式,多加个判断而已,但是如果换成非递归算法那就是相当于一个3*3的填格子问题了。不过问题本质没有改变,依然是拥有多个交叉子问题,然后做选择,将一系列子问题递推最终得出最优解的过程,即动态规划的经典思路。
ok,好久没更新写过博客类的东西了,发现了这个问题感觉回想起大学写上算法课的思考过程,特此记录一下,顺带复习下0-1揹包。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章