美文网首页算法和数据结构
背包问题(完全背包)

背包问题(完全背包)

作者: Mereder | 来源:发表于2019-04-28 20:51 被阅读15次

动态规划合集:

1.矩阵链乘法
2.投资组合问题
3.完全背包问题
4.01背包问题
5.最长公共子序列

例题3——背包问题

描述

一个背包,可以放入n种物品,物品j的重量和价值分别为w_j,v_j,j=1,2,\cdots,n,如果背包的最大重量限制是b,怎么样选择放入背包的物品以使得背包的总价值最大?

组合优化问题,设x_j表示装入背包的第j个物品的数量,解可以表示为<x_1,x_2,\cdots,x_n>。那么目标函数和约束条件是:
目标函数:max\sum_{j=1}^{n}v_jx_j \\ 约束条件:\begin{cases} \sum_{j=1}^{n}w_jx_j \le b \\ x_j \in N \end{cases}
如果组合优化问题的目标函数和约束条件都是线性函数,称为线性规划。如果线性规划问题的变量x_j都是非负整数,则称为整数规划问题。背包问题就是整数规划问题。限制所有的x_j=0 \ or \ x_j=1时称为0-1背包

子问题的界定(就是靠什么来划分子问题):由参数k和y界定

k:考虑对物品1,2,3,...,k的选择。

y:表示背包总重

子问题计算顺序:k=1,2,...,k,对给定的k,y=1,2,...,b

F_k(y):装前k个物品,重量不超过y时的背包最大值。
\begin{array} {l}{F_{k}(y)=\max \left\{F_{k-1}(y), F_{k}\left(y-w_{k}\right)+v_{k}\right\}} \\ {F_{0}(y)=0, \quad 0 \leq y \leq b, \quad F_{k}(0)=0, \quad 0 \leq k \leq n} \\ {F_{1}(y)= \lfloor\frac{y}{w_{1}}\rfloor v_{1}, \\ F_{k}(y)=-\infty \quad y<0.} \end{array}
F_k(y)包含两种情况:不装第k种物品或至少装一件第k种物品。

F_k(y-w_k)+v_k的解释:装一件第k种物品后,最优的解法仍然是在前k个物品进行选择,仍有可能再选入1件第k种物品。

对边界条件:

F_1(y) = \lfloor\frac{y}{w_1}\rfloor v_1:即只用第一种物品背包重量限制为y的最大价值,为了保证背包不超重,第一种物品至多能装\lfloor\frac{y}{w_1}\rfloor个,因为背包价值为\lfloor\frac{y}{w_1}\rfloor v_1

F_k(y) = - \infty,\quad y<0 有些F_k(y-w_k)<0那么通过设置为负无穷,在选择过程中抛弃掉为负的情况。

标记函数:用来追踪解
i_k(y):装前k种物品,总重不超过y,背包达到最大值时装入物品的最大标号 \\ i_{k}(y)=\left\{\begin{array}{ll}{i_{k-1}(y)} & {F_{k-1}(y)>F_{k}\left(y-w_{k}\right)+v_{k}} \\ {k} & {F_{k-1}(y) \leq F_{k}\left(y-w_{k}\right)+v_{k}}\end{array}\right.\\ i_{1}(y)=\left\{\begin{array}{ll}{0} & {y<w_{1}} \\ {1} & {y \geq w_{1}}\end{array}\right.

实例

n=4,b=10 \\ v_1=1,v_2=3,v_3=5,v_5=9 \\ w_1=2,w_2=3,w_3=4,w_4=7 \\

{F_{k}(y)=\max \left\{F_{k-1}(y), F_{k}\left(y-w_{k}\right)+v_{k}\right\}}

按照递推公式:以k=2为例子,简单演算如下:

{F_2(1)=\max \{F_{2-1}(1), F_{2}(1-w_{2})+v_{2}\}} = max\{0,-\infty\} = 0

{F_2(2)=\max \{F_{2-1}(2), F_{2}(2-w_{2})+v_{2}\}} = max\{1,-\infty\} = 1

{F_2(3)=\max \{F_{2-1}(3), F_{2}(3-w_{2})+v_{2}\}} = max\{1,3 \} = 3

{F_2(4)=\max \{F_{2-1}(4), F_{2}(4-w_{2})+v_{2}\}} = max\{2,3 \} = 3

{F_2(5)=\max \{F_{2-1}(5), F_{2}(5-w_{2})+v_{2}\}} = max\{2,1+3 \} = 4

{F_2(6)=\max \{F_{2-1}(6), F_{2}(6-w_{2})+v_{2}\}} = max\{2,3+3 \} = 6

依次类推,可得备忘录表:

备忘录表

标记函数的备忘录:

标记函数表

关于背包问题的总结

物品受限背包:第i种物品最多用n_i

0-1背包问题x_i = 0\ or\ 1,i=1,2,\cdots,n

多背包:m个背包,背包j装入最大重量B_j,j=1,2,\cdots,m在满足所有背包重量约束下使物品价值最大。

二维背包:每件物品重量w_i和体积t_j,i=1,2,\cdots,n,背包总重不超过b,体积不超过V,使得物品价值最大。

代码实现

此问题是完全背包问题,即 一个物品可重复出现。

public class knapsackProblem {
    public static int[][]mem; // 备忘录表
    public static int[][]s; // 标记函数表
    public static void main(String[] args) {
        int n = 4;
        int d = 10;
        int []w = {2,3,4,7};
        int []v = {1,3,5,9};

        mem = new  int[n+1][d+1];
        s = new int[n+1][d+1];  
        // 默认初始化为0

        int max_value = Completely_backpack(w,v,n,d);
        System.out.printf("背包最大值为:%d\n",max_value);
        System.out.printf("备忘录表为:\n");

        for (int i = 0; i < n + 1; i++) {
            for (int j = 0; j < d + 1; j++) {
                System.out.printf("%d ",mem[i][j]);
            }
            System.out.println();
        }

        System.out.println("标记函数表尾:");
        for (int i = 0; i < n + 1; i++) {
            for (int j = 0; j < d + 1; j++) {
                System.out.printf("%d ",s[i][j]);
            }
            System.out.println();
        }
        // 追踪解 且 初始化为 0
        int []res = new int[n+1];
        traceSolution(res,n,d,w);
        System.out.println("背包装入各个物品的数量为:");
        for (int i = 1; i < n + 1; i++) {
            System.out.printf("%d ",res[i]);
        }
    }

    public static int Completely_backpack(int []w,int []v,int n,int d){
        // F_k(y) = max{F_{k-1}(y), F_k(y-w_k)+v_k }
        // i表示 前i个 物品放入背包
        for (int i = 1; i <= n; i++) {
            // j 表示  背包重量为j
            for (int j = 1; j <= d; j++) {
                int not = mem[i-1][j];
                // w[i-1]是因为 w下标从0 开始,而i从1开始
                int in;
                if (j-w[i-1] < 0){
                    in = Integer.MIN_VALUE;
                }
                else in = mem[i][j-w[i-1]] + v[i-1];

                mem[i][j] = Math.max(not,in);
                // 根据标记函数的定义来写
                if (not > in){
                    s[i][j] = s[i-1][j];
                }
                else{
                    s[i][j] = i;
                }
            }
        }
        return mem[n][d];
    }

    public static void traceSolution(int []res,int n,int d,int []w){
        int y = d;
        for (int i = n; i >0 ;) {
            int temp = s[i][y];
            while(temp == i){
                // i-1 符合w的下标
                y = y-w[i-1];
                res[i]++;
                temp = s[i][y];
            }
            i = s[i][y];
        }
    }
}

相关文章

  • 背包问题(完全背包)

    动态规划合集: 1.矩阵链乘法2.投资组合问题3.完全背包问题4.01背包问题5.最长公共子序列 例题3——背包问...

  • 背包问题2(完全背包)

    01背包是指每件物品有且只有一件,而完全背包则是每件物品件数无限,求装入背包所对应的最值。完全背包也有公式,在01...

  • 动态规划完全背包01

    完全背包 和01背包一样力扣上没有没有纯完全背包问题,都是需要完全背包的各种应⽤,需要转化成完全背包问题,所以我们...

  • 完全背包问题

    相比于01背包问题只是单纯的多了一个条件:物品可以重复利用。 这是01背包问题的状态转移方程: 当W-wi大于0时...

  • 完全背包问题

    有n个重量和价值分别为wi,vi的物品。从这些物体中挑选出总重量不超过W的物品,求所有方案中价值总和的最大值。在这...

  • 完全背包问题

    https://www.cnblogs.com/A1269180380/p/6344043.html 注意数组的遍...

  • 背包系列问题之--完全背包问题

    问题描述 小偷深夜潜入一家珠宝店,店里有5类宝物,每类宝物体积分别为W{1,3,2,4,5},对应的价值为V{20...

  • 算法-动态规划-背包问题

    背包问题是基础的动态规划问题,包含了0-1背包,完全背包,多重背包等。 0-1背包 存在容量为 的背包 , 件体...

  • 动态规划之背包问题(01背包,完全背包,多重背包)

    01背包 问题描述 有N个物品,每个物品的重量为weight[i],每个物品的价值为value[i]。现在有一个背...

  • 01背包问题(完全背包,部分背包)golang实现

    很经典的动态规划问题,具体思路这里就不列出了,网上太多资料了。想要详细理解的话可以去看背包九讲这里分别列出,01背...

网友评论

    本文标题:背包问题(完全背包)

    本文链接:https://www.haomeiwen.com/subject/lifsnqtx.html