动态规划算法学习三:0-1背包问题

简介: 这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。

前言

一、问题描述

在这里插入图片描述
在这里插入图片描述

二、DP解决步骤

1、最优子结构性质

在这里插入图片描述

2、状态表示和递推方程

  • 子问题可由两个参数确定:待考虑装包的物品集背包的容量
  • 将所有物品按照1至n 标号,待考虑装包的物品集可以用物品集中末尾物品的标号来描述,则得状态表示𝑽𝒂𝒍(𝒊,𝒑),1≤𝑖≤𝑛, 0≤𝑝≤𝐶 表示在背包容量为𝑝,待考虑装包的物品集为{1, 2, …, i}时的最大装入物品价值。
  • Val(n, C) 则表示原问题的最优解。

3、算法设计与分析

𝑽𝒂𝒍(𝒊,𝒑),1≤𝑖≤𝑛, 0≤𝑝≤𝐶 表示在背包总容量𝑝,待考虑装包的物品集为{1, 2, …, i} 时的最大装入物品价值。
在这里插入图片描述

解释上图:

  • 当 i = 1时:
    • 如果$w_1$ > p,说明放不下背包,则价值为 0;
    • 如果$w_1$< p,则能放进去,且价值为 $v_1$。
  • 当 i > 1时:
    • 如果$w_i$> p 时,说明,整个包都放不下一个第i个物品,则这个物品可以舍弃,且价值为之前的i-1的价值 即:Val(i - 1,p)
    • 如果$w_i$< p时,说明,这个包是可以放得进去背包的,则需要判断值不值的:
      整个包能放下第i个物品,只有两种可能性:
      1. 不放第i个物品:价值仍然是val(i-1,p)
      2. 放入第i个物品:包中需要为其腾出 $w_i$的空;那么前i-1个物品就只能从p-$w_i$的空中选取最佳组合,其最佳组合值为 val(i-1,p-$w_i$) ;然后再加上$v_i$;
      然后,对这两种可能的子问题的最优值进行max;
      注意:前i-1个物品在不同的包容量Px下,其组合都是不同的,但是最佳值都可以用val(i-1,Px)来表示。在自底向上方法下,Px可以逐步累加,来求解val(i-1,Px)的值。

4、计算最优值

在这里插入图片描述
在这里插入图片描述

按物品的两种基本单位来给出表格的行数和列数,而不是根据物品的数目和价值!有枚举的意思,回顾暴力算法章节中剪绳子的问题!
3-6处的9:能放进去,但价值会降低,不腾,不放
3-8处的11:能放进去,但要腾1个,价值会升高,腾,放
3-10处的14:能放进去,但剩余空间够,不必腾,放,价值会升高

在这里插入图片描述

按照上面公式以及逻辑计算:

  1. i = 1时,有11个情况,0-10,
    物品只有第一个,n=1;
    只有 p = 2及以后, p>=($w_1$ = 2),$v_1$ = 6,所以背包从 2 开始到 10 都是 6
    (这里是第一个公式,往后就只使用第二个公式进行比较)
  2. i = 2时,11个情况,0-10
    物品是前2个,n=2;
    p = 2时,满足p >= ($w_2$ = 2),可以替换,但需要比较 是否值得替换:Val(i-1, p)=Val(1,2)=6,Val(i-1, p - $w_2$)+$v_2$= Val(1,0)+3 = 3,3<;虽然能替换,放了还不如原来的价值,所以不替换。背包放 1 号物品;
    p = 3时,同上。
    p = 4时及以后(从逻辑上讲:背包放1号和2号物品,即9 正好,但是也需要计算)。p > ($w_2$ = 2),可以放,但需要比较 是否值得放:Val(i-1, p)=Val(1,4)=6,Val(i-1, p - $w_2$)+$v_2$= Val(1,2)+3 = 9,9>6,则可以放。
  3. i = 3时,11个情况,0-10
    物品有3个,n=3;
    p = 2时,同上面的 p = 2 的逻辑。放物品1
    p = 4时,同上面的 p = 4 的逻辑。放物品1,2
    p = 8时,p >= ($w_3$ = 6),可以替换,但需要比较 是否值得替换:Val(i-1, p)=Val(2,8)=9,Val(i-1, p - $w_3$)+$v_3$= Val(2,2)+5 = 11,11>9,所以可以替换。把n=2拿出来,把n=3放进去,权重相加等于8,价值为11;放物品1,3
    p = 10时,p >= ($w_3$ = 6),可以替换,但需要比较 是否值得替换 :Val(i-1, p)=Val(2,10)=9,Val(i-1, p - $w_3$)+$v_3$= Val(2,4)+5 = 14。三个都可以放进去,则价值为14。放物品1,2,3
  4. i = 4时,11个情况,0-10
    物品有4个,n=4;
    p = 2时,同上面的 p = 2 的逻辑。放物品1
    p = 4时,同上面的 p = 4 的逻辑。放物品1,2
    P = 7时,p >= ($w_4$ = 5),可以替换,但需要比较 是否值得替换 ,Val(i-1, p)=Val(3,7)=9,Val(i-1, p - $w_4$)+$v_4$= Val(3,2)+4 = 10,因为 9 < 10,所以可以放。放物品1,4
    P = 8时,p >= ($w_4$ = 5),可以替换,但需要比较 是否值得替换 ,Val(i-1, p)=Val(3,8)=11,Val(i-1, p - $w_4$)+$v_4$= Val(3,3)+4 = 10,因为 11 > 10,所以替换,放物品1,3
    P = 9时,p >= ($w_4$ = 5),可以替换,但需要比较 是否值得替换 ,Val(i-1, p)=Val(3,9)=11,Val(i-1, p - $w_4$)+$v_4$= Val(3,4)+4 = 13,因为 11 < 13 ,所以替换,放物品1,2,4
    P = 10时,p >= ($w_4$ = 5),可以替换,但需要比较 是否值得替换 ,Val(i-1, p)=Val(3,10)=14,Val(i-1, p - $w_4$)+$v_4$= Val(3,5)+5 = 14,因为 14 = 14 ,所以替换,存物品1,2,3
  5. i = 5时,11个情况,0-10
    物品有5个,n=5;

5、算法实现

import java.util.Arrays;

import static java.lang.Math.max;

/**
 * DP之0-1背包问题
 */
public class Main3 {

    public static int MaxN = 11;
    public static int MaxC = 11;

    public static void main(String[] args) {
        int[] w = {2, 2, 6, 5, 4};
        double[] v = {6, 3, 5, 4, 6};
        double v1 = binaryKnapsack(w.length, w, v, 10);
        System.out.println(v1);
    }

    public static double binaryKnapsack(int numItems, int[] w, double[] v, int capacity) {
        double[][] val = new double[numItems][capacity + 1];
        memSet(val, 0, val.length);

        for (int i = 1; i < numItems; i++)
            for (int j = 0; j <= capacity; j++) {
                val[i][j] = val[i - 1][j];
                if (j >= w[i])
                    val[i][j] = max(val[i - 1][j], val[i][j - w[i]] + v[i]);
            }

        // 打印二维数组
        for (int i = 0; i < val.length; i++) {
            System.out.println(Arrays.toString(val[i]));
        }
        return val[numItems - 1][capacity]; // [4][10]
    }

    public static void memSet(double[][] val, int col, int length) {
        for (int i = 0; i < length; i++) {
            for (int j = 0; j < val[i].length; j++){
                val[i][j]=0;
            }
        }
    }

}

计算 𝑣𝑎𝑙(𝑖,𝑝)的值只需要Val数组中第𝒊−𝟏行中第𝑝个分量之前的数值。

6、缺点与思考

在这里插入图片描述

相关文章
|
3天前
|
存储 算法
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
这篇文章详细介绍了图的概念、表示方式以及深度优先遍历和广度优先遍历的算法实现。
13 1
数据结构与算法学习二二:图的学习、图的概念、图的深度和广度优先遍历
|
1天前
|
算法
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
这篇文章介绍了动态规划算法中解决最大上升子序列问题(LIS)的方法,包括问题的描述、动态规划的步骤、状态表示、递推方程、计算最优值以及优化方法,如非动态规划的二分法。
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
|
1天前
|
算法
动态规划算法学习二:最长公共子序列
这篇文章介绍了如何使用动态规划算法解决最长公共子序列(LCS)问题,包括问题描述、最优子结构性质、状态表示、状态递归方程、计算最优值的方法,以及具体的代码实现。
动态规划算法学习二:最长公共子序列
|
1天前
|
缓存 负载均衡 算法
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
Nginx 是一款高性能的 HTTP 和反向代理服务器,也是一个通用的 TCP/UDP 代理服务器,以及一个邮件代理服务器和通用的 HTTP 缓存服务器。
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
|
1天前
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
|
9天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于MSER和HOG特征提取的SVM交通标志检测和识别算法matlab仿真
### 算法简介 1. **算法运行效果图预览**:展示算法效果,完整程序运行后无水印。 2. **算法运行软件版本**:Matlab 2017b。 3. **部分核心程序**:完整版代码包含中文注释及操作步骤视频。 4. **算法理论概述**: - **MSER**:用于检测显著区域,提取图像中稳定区域,适用于光照变化下的交通标志检测。 - **HOG特征提取**:通过计算图像小区域的梯度直方图捕捉局部纹理信息,用于物体检测。 - **SVM**:寻找最大化间隔的超平面以分类样本。 整个算法流程图见下图。
|
4天前
|
算法
基于粒子群算法的分布式电源配电网重构优化matlab仿真
本研究利用粒子群算法(PSO)优化分布式电源配电网重构,通过Matlab仿真验证优化效果,对比重构前后的节点电压、网损、负荷均衡度、电压偏离及线路传输功率,并记录开关状态变化。PSO算法通过迭代更新粒子位置寻找最优解,旨在最小化网络损耗并提升供电可靠性。仿真结果显示优化后各项指标均有显著改善。
|
1天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于WOA鲸鱼优化的GroupCNN分组卷积网络时间序列预测算法matlab仿真
本项目展示了一种基于WOA优化的GroupCNN分组卷积网络时间序列预测算法。使用Matlab2022a开发,提供无水印运行效果预览及核心代码(含中文注释)。算法通过WOA优化网络结构与超参数,结合分组卷积技术,有效提升预测精度与效率。分组卷积减少了计算成本,而WOA则模拟鲸鱼捕食行为进行优化,适用于多种连续优化问题。
|
2天前
|
机器学习/深度学习 算法 5G
基于BP神经网络的CoSaMP信道估计算法matlab性能仿真,对比LS,OMP,MOMP,CoSaMP
本文介绍了基于Matlab 2022a的几种信道估计算法仿真,包括LS、OMP、NOMP、CoSaMP及改进的BP神经网络CoSaMP算法。各算法针对毫米波MIMO信道进行了性能评估,通过对比不同信噪比下的均方误差(MSE),展示了各自的优势与局限性。其中,BP神经网络改进的CoSaMP算法在低信噪比条件下表现尤为突出,能够有效提高信道估计精度。
12 2
|
11天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于GA遗传优化的GroupCNN分组卷积网络时间序列预测算法matlab仿真
该算法结合了遗传算法(GA)与分组卷积神经网络(GroupCNN),利用GA优化GroupCNN的网络结构和超参数,提升时间序列预测精度与效率。遗传算法通过模拟自然选择过程中的选择、交叉和变异操作寻找最优解;分组卷积则有效减少了计算成本和参数数量。本项目使用MATLAB2022A实现,并提供完整代码及视频教程。注意:展示图含水印,完整程序运行无水印。