代码随想录 Day35 动态规划04 01背包问题和完全背包问题 LeetCode T416 分割等和子集

背包问题

说到背包问题大家都会想到使用动规的方式来求解,那么为什么用动规呢,dp数组代表什么呢?初始化是什么,遍历方式又是什么,这篇文章笔者将详细讲解背包问题的经典例题0-1背包问题和完全背包问题的解题方式,希望能帮助到大家

1.暴力方式

有人一提到背包问题就只会使用动态规划来做,那么背包问题假如让你使用暴力求解该如何解决呢?我们以0-1背包为例,每个物品是不是只有两种状态?放或者不放,我们可以遍历所有方式,使用回溯来解决问题.

0-1背包问题解决方式(二维数组)

动规五部曲

1.明白dp数组的含义

此处dp[i][j]表示的就是从[0,i]个物品中任选,用容量为j的背包能装的最大价值.

2.数组的初始化和递推公式的理解

递推公式:

不放物品:其实就是延续上一层的最大价值即可

dp[i][j] = dp[i-1][j]

放入物品:取上一层的数据或者放入这一层的物品加上剩下的容量的最大价值,两者之间取最大值即可

dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])

初始化数组:

首先从定义出发dp[i][0]一定得初始化为0,0容量的背包装不了东西

由于每一行的数据都是由上一行推导产生的,所以第一行的数据我们也要进行初始化,i从weight[0]开始初始化就行,因为背包的容量的大于等于第一个物品的容量才能装的进去它.

3.遍历顺序的理解

这里我们可以感受一下先遍历背包和先遍历物品的区别,其实都可以达到我们的效果,但是先

遍历物品更好理解

那么为什么两种遍历方式都可以解决问题呢?

如下图所示,因为无论是哪种遍历方式,我们的dp[i][j]都是由左上角的元素推导出来的,所以无所谓用哪种遍历顺序都可以.

 for(int i = 1;i<goods;i++){
            for (int j = 1; j <= bagSize; j++) {
                if(j<weight[i]){
                    dp[i][j] = dp[i-1][j];
                }else{
                    dp[i][j] = Math.max(dp[i-1][j],value[i]+dp[i-1][j-weight[i]]);
                }
            }
        }

4.打印数组进行查看

0-1背包示例代码

    public static void func1(int[] weight, int[] value, int bagSize){

        //初始化dp数组
        int goods = weight.length;
        int[][] dp = new  int[goods][bagSize+1];
        for (int i = weight[0]; i <=bagSize; i++) {
            dp[0][i] = value[0];
        }
        for(int i = 1;i<goods;i++){
            for (int j = 1; j <= bagSize; j++) {
                if(j<weight[i]){
                    dp[i][j] = dp[i-1][j];
                }else{
                    dp[i][j] = Math.max(dp[i-1][j],value[i]+dp[i-1][j-weight[i]]);
                }
            }
        }
        for (int i = 0; i < goods; i++) {
            for (int j = 0; j <=bagSize; j++) {
                System.out.print(dp[i][j]+" ");
            }
            System.out.println();
        }




    }












//main方法中代码
        int[] value = {15,20,30};
        int[] weight = {1,3,4};
        int bagSize = 4;
        func1(weight,value,bagSize);

0-1背包问题解决方式(一维数组)

1.明白dp数组的含义

这里使用一维数组滚动覆盖来代替二维数组,就类似于将一个矩阵压成了一行

我们先回顾一下二维数组的含义dp[i][j]:从[0,i]的物品中,背包容量为j能装的最大价值

这里的dp[j]就是背包容量为j能装的最大价值

其实可以发现如果把dp[i - 1]那一层拷贝到dp[i]上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);

2.递推公式的理解

我们知道dp[j]可以通过dp[j - weight[i]]推导出来,dp[j - weight[i]]表示容量为j - weight[i]的背包所背的最大价值。

然后递推公式由两个选择,一个是上一层的值和本层的物品价值加上剩余空间价值的较大值

dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

3.数组的初始化

根据上面的递推公式,我们知道初始化一定不能初始化成一个大值,因为可能太大了而导致后面的dp[j-weight[i]]+value[i]无法覆盖他的值,所以我们初始化为0即可

4.遍历顺序的理解

我们先上代码,后讲解原因

我们发现这里的背包遍历是从后向前遍历的,为什么呢,举个例子

如果是从前向后遍历

那么dp[1] = dp[1-1]+value[0] = 15

dp[2] = dp[2-1] +value[0]= 30

这不符合我们0-1背包的每件物品只能使用一次的逻辑,因为这里物品1被放入了两次

而我们从后向前遍历就可以避免这个问题

dp[4] = dp[3]+value[0];

dp[3] = dp[2]+value[0];

...这里就不会存在重复计算问题

为什么上面二维数组的遍历不需要倒序呢?

因为二维数组的dp[i][j]是由上一层的元素推导出来,不会影响本层的元素

以为数组的遍历顺序只能是先遍历物品,再遍历背包!!!

我们还是举个例子来说明(一维数组,我们以二维数组的形式画出来),我们就会发现,如果用容量来遍历物品的话,其实就是每个容量的背包只取得了一个物品,与答案相悖

for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    }
}

5.打印数组进行查看

示例代码 

   public static void func2(int[] weight, int[] value, int bagWeight) {
        int wLen = weight.length;
        //定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值
        int[] dp = new int[bagWeight + 1];
        //遍历顺序:先遍历物品,再遍历背包容量
        for (int i = 0; i < wLen; i++) {
            for (int j = bagWeight; j >= weight[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }
        //打印dp数组
        for (int j = 0; j <= bagWeight; j++) {
            System.out.print(dp[j] + " ");
        }
    }
}

LeetCode T416 等和子集问题

题目链接:416. 分割等和子集 - 力扣(LeetCode)

题目思路:

利用上述思路,这里的背包容量是数组之和的一半,重量和价值数组都等于源数组,上面给出一定的剪枝,假如出现奇数就直接返回false,出现只有一个元素也直接返回false,下面我给出解题代码.

题目代码:

class Solution {
    public boolean canPartition(int[] nums) {
        if(nums.length == 1){
            return false;
        }
        int sum = 0;
        for(int i:nums){
            sum += i;
        }
        if(sum % 2 == 1){
            return false;
        }
        int bagSize = sum/2;
        int[] dp = new int[bagSize+1];
        //初始化均为0
        for(int i = 0;i<nums.length;i++){
            for(int j = bagSize;j>=nums[i];j--){
                dp[j] = Math.max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        if(dp[bagSize] == bagSize){
            return true;
        }
       return false;

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/113914.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL 多表联查详解

目录 一、一个案例引发的多表连接 二、笛卡尔积的错误和与正确的多表查询 2.1、笛卡尔积错误展示 2.2、笛卡尔积解决方法 2.3、练习 三、多表查询分类 3.1、等值连接 vs 非等值连接 3.2、自连接 vs 非自连接 3.3、内连接 vs 外连接 内连接&#xff08;inner join&…

jetsonTX2 nx配置yolov5和D435I相机,完整步骤

转载一篇问题解决博客&#xff1a;问题解决 一、烧录系统 使用SDK烧录 二、安装archiconda3 JETSON TX2 NX的架构是aarch64,与win10,linxu不同,所以不能安装Anaconda&#xff0c;这里安装对应的archiconda。 1. 安装 wget https://github.com/Archiconda/build-tools/rel…

第16期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

VMware——VMware17设置WindowServer2012R2环境静态IP及关闭防火墙

目录 一、VMware17设置WindowServer2012R2环境静态IP1.1、工具栏虚拟机的设置步骤1.2、工具栏编辑的设置步骤1.3、静态IP的设置步骤 二、VMware17关闭WindowServer2012R2环境防火墙 一、VMware17设置WindowServer2012R2环境静态IP 1.1、工具栏虚拟机的设置步骤 打开VMware虚拟…

box-shadow

0 参数解释 box-shadow:inset offset-x offset-y blur-radius spread-radius color; **inset&#xff1a;**有inset 则为内阴影&#xff0c;没有insert 则为外阴影&#xff0c;默认为外阴影 **offset-x&#xff1a;**横向阴影的大小。正值阴影在右边&#xff1b;负值阴影在左边…

基于深度学习的目标检测算法 计算机竞赛

文章目录 1 简介2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 1 简介 &#x1f5…

linux查看文件夹使用情况以及查看文件大小

1、ls ls 命令是 Linux 中最常用的文件和目录列表命令之一。它可以显示文件的各种属性&#xff0c;包括文件大小。 ls -l <文件名>上述命令会显示文件的详细信息&#xff0c;其中包括文件的大小。文件大小以字节为单位显示&#xff0c;并且在输出中的第 5 列。4096 表示…

【实战Flask API项目指南】之六 数据库集成 SQLAlchemy

实战Flask API项目指南之 数据库集成 本系列文章将带你深入探索实战Flask API项目指南&#xff0c;通过跟随小菜的学习之旅&#xff0c;你将逐步掌握 Flask 在实际项目中的应用。让我们一起踏上这个精彩的学习之旅吧&#xff01; 前言 在上一篇文章中&#xff0c;我们实现了…

出海营销必看:如何避免邮件被识别为垃圾邮件

对于现在的商业环境来说&#xff0c;邮件通信已经成为企业与客户、合作伙伴以及员工之间沟通和交流的重要方式。然而&#xff0c;尽管企业发送的邮件通常都是正常的、合规的&#xff0c;有时候却会被系统错误地标记为营销邮件。这个情况给企业带来了很多困扰。 如果企业的邮件…

FMC子卡解决方案:FMC214-基于FMC兼容1.8V IO的Full Camera Link 输出子卡

FMC214-基于FMC兼容1.8V IO的Full Camera Link 输出子卡 一、板卡概述   基于FMC兼容1.8V IO的Full Camera Link 输出子卡支持Base、Middle、Full Camera link信号输出&#xff0c;兼容1.8V、2.5V、3.3V IO FPGA信号输出。适配xilinx不同型号开发板和公司内部各FMC载板。北…

Langchain-Chatchat项目:4.1-P-Tuning v2实现过程

常见参数高效微调方法(Parameter-Efficient Fine-Tuning&#xff0c;PEFT)有哪些呢&#xff1f;主要是Prompt系列和LoRA系列。本文主要介绍P-Tuning v2微调方法。如下所示&#xff1a; Prompt系列比如&#xff0c;Prefix Tuning(2021.01-Stanford)、Prompt Tuning(2021.09-Goo…

图片去水印不伤原图快来试试这些方法

也许很多朋友都曾经历过和我相似的困扰。费尽心思找到心仪的图片&#xff0c;却发现下载的图片大多都带有水印。尝试了各种方法想要消除图片上的水印&#xff0c;但效果不尽如人意&#xff0c;反而让画面变得更加凌乱模糊&#xff0c;那么&#xff0c;有什么方法可以图片去水印…

点击跳到详情页

父页面 <template><view class"order-list"><cu-custom bgColor"bg-gradual-blue" :isBack"true"><block slot"content">荒料管理</block></cu-custom><view class"" ><!-- 订…

物流小程序制作教程:从零到有,详细解析

随着互联网的快速发展&#xff0c;物流行业也逐渐实现了数字化转型。为了满足消费者对更加便捷、高效的服务需求&#xff0c;许多物流企业选择制作自己的小程序。本文将通过乔拓云网后台&#xff0c;带你轻松搭建物流小程序&#xff0c;主要分为以下几个部分&#xff1a; 一、进…

Github 自动化部署到GitHub Pages

1.准备工作 新建仓库 新建项目 配置 vite.config.ts base: ./,部署应用包时的基本URL&#xff0c;例&#xff1a;vue-cli 5.x 配置 publicPath 推送到远程仓库 2.配置 GitHub Token 点击 Settings -> Actions -> General 找到 Workflow permissions&#xff0c;选中第…

名称空间,作用域,global和nonlocal

一、名称空间 加载顺序&#xff1a; 1、内置命名空间 2、全局命名空间 3、局部命名空间 取值顺序&#xff1a; 1、局部命名空间 2、全局命名空间 3、内置命名空间 二、作用域 三、global python之闭包https://blog.csdn.net/Python_1981/article/details/133636994 四…

串口通信(8)串口中断“边接收边解析数据“的通信程序

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

JavaScript 基础

文章目录 JavaScript初识JavaScriptJavaScript 的组成第一个程序 语法变量的使用动态类型基本数据类型number 数字类型string 字符串类型转义字符求长度字符串拼接 boolean 布尔类型undefined 未定义数据类型null 空值类型 运算符数组数组的遍历函数 对象使用 字面量 创建对象 …

openGauss学习笔记-112 openGauss 数据库管理-管理用户及权限-行级访问控制

文章目录 openGauss学习笔记-112 openGauss 数据库管理-管理用户及权限-行级访问控制 openGauss学习笔记-112 openGauss 数据库管理-管理用户及权限-行级访问控制 行级访问控制特性将数据库访问控制精确到数据表行级别&#xff0c;使数据库达到行级访问控制的能力。不同用户执…

ZYNQ实验---IQ调制实现SSB PART2

一、前言 本文实验在ZYNQ实验—IQ调制实现SSB PART1的基础上进行优化完善。 下图为IQ调制实现SSB PART1中设想实现设计框图 该图设计存在的几个问题&#xff1a; PC-PS的UDP传输存在丢包中断控制发包实际不适合流数据的传输采用的BRAM模块可以存储的空间较小&#xff0c;PC…