代码随想录 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];//初始化均为0for(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;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenGL ES入门教程(一)编写第一个OpenGL程序

OpenGL ES入门教程&#xff08;一&#xff09;编写第一个OpenGL程序 前言 从本文开始我将参考学习OpenGL ES应用开发实践指南 Android卷 [&#xff08;美&#xff09;KevinBrothaler著]&#xff08;提取码: 394m&#xff09;&#xff0c;并基于自己的理解以更加通俗易懂的方式…

近独立粒子的最概然分布

近独立粒子&#xff1a;粒子之间相互作用微弱基本粒子中&#xff0c;自旋量子数为半整数的有 电子 、 质子 、中子、中微子自旋量子数为整数的有 光子、pi介子 经典力学描述系统的微观运动状态 经典力学中&#xff0c;全同粒子可以分辨量子力学&#xff0c;全同粒子不可以分辨微…

2023-11-02 LeetCode每日一题(环和杆)

2023-11-02每日一题 一、题目编号 2103. 环和杆二、题目链接 点击跳转到题目位置 三、题目描述 总计有 n 个环&#xff0c;环的颜色可以是红、绿、蓝中的一种。这些环分别穿在 10 根编号为 0 到 9 的杆上。 给你一个长度为 2n 的字符串 rings &#xff0c;表示这 n 个环在…

BetterDisplay Pro v1.4.15(显示器管理管理软件)

BetterDisplay Pro是一款屏幕显示优化工具&#xff0c;可用于Windows和Mac操作系统。它可以帮助用户调整屏幕的亮度、对比度、色彩等参数&#xff0c;以获得更好的视觉体验。此外&#xff0c;BetterDisplay Pro还提供了一些额外的功能&#xff0c;如屏幕分割、窗口管理、快捷键…

Django3框架-(3)-[使用websocket]:使用channels实现websocket功能;简化的配置和实际使用方式

概述&#xff1a; 对于Django使用channels实现websocket的功能&#xff0c;之前就写了几篇博文了。随着在项目的使用和实际维护来说&#xff0c;重新设置了相关处理方法。 一般来说&#xff0c;前后端都只维护一个全局的连接&#xff0c;通过携带数据来判断具体的操作&#x…

Flink1.18新特性生产环境应用的重点解读!

大家好&#xff0c;我是你们的群主王知无呀。 Flink 1.18已经于近期发布了。在这个新版本中新增了很多新的功能和特性。在这些特性中&#xff0c;有一些是生产环境非常重要的能力&#xff0c;大家在使用过程中可以重点参考和了解其中的原理。 算子级别状态保留时间TTL设置 首先…

GitHub经常打不开或者访问解决办法

访问慢或无法访问的原因&#xff1a;DNS解析是最为基础的一个环节。由于Github的服务器在全球各地&#xff0c;域名解析所需的时间也会不同&#xff0c;这就导致了在特定地区可能会出现Github无法正常访问的情况。 解决&#xff1a;查询到github对应的IP&#xff0c;然后在host…

精准测试:提高软件质量和用户满意度的利器

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

腾讯云域名备案后,如何解析到华为云服务器Linux宝塔面板

一、购买域名并且进行备案和解析&#xff0c;正常情况下&#xff0c;购买完域名&#xff0c;如果找不到去哪备案&#xff0c;可以在腾讯云上搜索“备案”关键词就会出现了&#xff0c;所以这里不做详细介绍&#xff0c;直接进行步骤提示&#xff1a; 二、申请ssl证书&#xff0…

uniapp使用抖音微信自定义组件

tt.vue中使用video-player组件 用到的目录如下&#xff1a; pages.json {"path": "pages/Tabbar/tt/tt","style": {"navigationBarTitleText": "","enablePullDownRefresh": false,// 使用自定义组件"using…

Nginx服务器安装证书并启用SSL(acme.sh)

前提 您已购置vps服务器&#xff0c;例如阿里云全球站ecs、AWS EC2、Azure VM、GCP Compute等安全组已开启80、443端口&#xff0c;且访问源设置为0.0.0.0/0域名已设置A记录指向当前操作服务器&#xff0c;若您使用aws ec2&#xff0c;有公有 IPv4 DNS&#xff0c;可供使用 安…

2023年最新版潮乎盲盒源码含搭建教程

后台开发语言&#xff1a;后端 Laravel 框架开发 前端开发框架&#xff1a;uniappvue 环境配置: php7.4 mysql5.6 nginx1.22 redis&#xff08;建议宝塔面板或 lnmp&#xff09; 源码获取请自行百度&#xff1a;一生相随博客 一生相随博客致力于分享全网优质资源&#x…

Python条件判断的运用

问题 在生活中&#xff0c;我们可以通过判断条件是否成立&#xff0c;来决定执行哪个分支。选择语句有多种形式&#xff1a;if语句&#xff0c;if-else语句&#xff0c;if-elif-else语句等。 Python使用if条件判断语句来实现条件判断时&#xff0c;可以在多个循环中实现对问题的…

JAVA亡了?那么多岗位去哪了?

1.java现在有多卷&#xff1f; 虽然近年来出现了许多其他编程语言和技术。但JAVA依旧是热度最高的。它仍然被广泛用于大型企业应用、后端开发、Android应用开发以及嵌入式系统等领域。此外&#xff0c;Java在大数据、云计算和物联网等新兴领域也有着重要的地位。 因此&#x…

基于OR-Tools的装箱问题模型求解(PythonAPI)

装箱问题 一、背包问题&#xff08;Knapsack problem&#xff09;1.1 0-1背包模型基于OR-Tools的0-1背包问题求解&#xff08;PythonAPI&#xff09;导入pywraplp库数据准备声明MIP求解器初始化决策变量初始化约束条件目标函数调用求解器打印结果 1.2 多重背包问题&#xff08;…

一篇博客读懂顺序表 —— Sequence-List

目录 一、顺序表的初始定义 1.1新建头文件和源文件 1.2 SeqList.h 中的准备工作 二、顺序表的初始化与销毁 三、首尾插入元素 四、首尾删除元素 五、中间插入元素 六、中间删除元素 七、查找指定元素下标 八、源代码 一、顺序表的初始定义 1.1新建头文件和源文件 当我…

流媒体服务实现H5实时预览视频

目录 背景方案业务实践细节注意 待办 背景 客户aws服务磁盘存储告急&#xff0c;最高可扩容16T。排查如下&#xff1a;主要是视频文件存在大量复制使用的情况。例如发布节目时复制、预览时复制&#xff0c;这样上传一份视频后最大会有四份拷贝&#xff08;预览、普通发布、互动…

vue3简单写导航anchor示例(支持点击高亮和滚动判断高亮)

1. 点击anchor, 相应的anchorlink高亮 function anchorClick(index) { forceStop.value true; time Date.now(); wheelRef.value.children[index].scrollIntoView({ block: start, behavior: smooth }); // 给一些延时, 再点亮anchor, 同时不再限制scrol…

微信小程序 人工智能志愿者服务活动报名系统uniAPP+vue

基于java语言设计并实现了人工智能志愿者服务APP。该APP基于B/S即所谓浏览器/服务器模式&#xff0c;应用SpringBoot框架与HBuilder X技术&#xff0c;选择MySQL作为后台数据库。系统主要包括用户、志愿活动、活动报名、活动签到、服务职责、服务排行等功能模块。 本文首先介绍…

Zynq-Linux移植学习笔记之64- 国产ZYNQ在linux下配置国产5396芯片

1、背景介绍 复旦微ZYNQ通过SPI配置国产JEM5396&#xff0c;框图如下&#xff1a; 现在需要在linux下的应用程序内配置JEM5396的寄存器。其中FMQL和进口的XILINX ZYNQ类似&#xff0c;JEM5396和进口的BCM5396兼容。因此可以参考进口ZYNQ在linux下配置BCM5396过程。Zynq-Linux移…