01背包问题-递推公式的自我理解与LeetCode 416. 分割等和子集

news2025/1/19 2:36:42

学算法好痛苦,完全是对我智力的一次次折磨,看了好多博客,对二维dp数组的理解都是直接搬了代码随想录,搬了随想录又没详细解释,大家都是一眼看懂的吗,好吧()

LeetCode 416. 分割等和子集

  • 一、对二维dp数组的理解
    • 背景
    • dp[i][j]的推导
  • 二、优化:滚动一维数组
  • 例1 LeetCode 416. 分割等和子集
  • notes

一、对二维dp数组的理解

背景

  1. 如果有一个容量为j的这样的背包——一个独立的,容量为j的背包。(没把它理解为“剩余容量”)
  2. 对于这个背包,可以从编号为0至i的物品里任意挑,挑几个无所谓,挑多重的无所谓
  3. 计算第二步挑选的价值,取所有挑选中使整个背包价值最大的这次挑选,将最大的价值记为dp[i][j]
  4. 根据前三步,整体的dp[n][m]就是一个n+1行、m+1列的表格。取其中的一格看,比如第i行第j列的dp[i][j],它的含义为:对于容量为j的背包,编号0-i的物品随便挑,背包最大价值为多少。下面,我们详细说一下dp[i][j]的递推公式。

dp[i][j]的推导

  1. dp[i][j]的推导看起来很难,因为要对i+1个物品每个物品0~i都选择放或者不放,那么就 2 i + 1 2^{i+1} 2i+1次挑选
  2. 但是实际情况下,求dp[i][j]只需要考虑第i个物品的放与不放,也就是对于这个格子只要考虑对于1个物品的2次挑选方式(选与不选)+1次查表(查表——我们遍历表格dp[n][m]的时候已经填写了在dp[i][j]之前的格子,之前的最优挑选查找表格即可。)
  3. 为什么可以通过1次查表简化前 2 i 2^i 2i次挑选?
  • 首先,不考虑背包容量,如果我们需要dp[i][j]是价值最大的,那么可以分两种情况:在第三步选定“这次挑选”的时候,dp[i][j]【情况1:使整个背包价值最大的这次挑选含第i个物品】,【情况2:使整个背包价值最大的这次挑选不含第i个物品】,那么合起来
dp[i][j]=max{含第i个物品的挑选的背包价值,不含第i个物品的挑选的背包价值}
  • 其次,再考虑上背包容量,
    ①含第i个物品的挑选的背包价值:由于第i个物品占一定的容量,此时需要调整第0到第i-1个物品的挑选方式。因为需要预留第i个物品的容量,所以对于第0到第i-1个物品,最多只能j-weight[i]的容量,价值为查表得到的dp[i-1][j-weight[i]];对于第i个物品,确定是放,所以再加上它本身的价值value[i]。
    ②不含第i个物品的挑选的背包价值:与dp[i-1][j]相同。因为这种情况等于是从容量为j的背包里选,但只从第0到第i-1个物品里挑。
dp[i][j]
=max{含第i个物品的挑选的背包价值,同样大小的背包不含第i个物品的挑选}
=max{dp[i-1][j],dp[i-1][j-weight[i]]+value[i]}

在这里插入图片描述
备注:①中还需要判断 j 是否小于 weight[i],不然j-weight[i]就变成负值,无法成为数组下标。

二、优化:滚动一维数组

如不考虑中间状态,可优化空间复杂度,仅使用j+1个空间,而非(i+1)*(j+1)个。
在这里插入图片描述
需要逆序(遍历 j 时),以保证从后往前的时候前面的初始化是没动的,不然dp[j-weight[i]]的计算会用到前面已经加过value[i]的元素,从而再加一个。这个看代码随想录手动推一遍还是比较简单,故不细说。

例1 LeetCode 416. 分割等和子集

由于看了之前的0-1背包,被困住了思路,老是觉得0-1背包是求的一堆元素的“最大值”,而等和子集求的是一堆元素等于某个值的情况,思想上感觉不一样。知道回溯法不配合剪枝肯定不行(200个num, 2 200 2^{200} 2200
然后隔了一天看了别人没学代码随想录的题解,发现其实很简单,因为我误认为我这里的dp[][]里存放的是和,或者一个特定的值什么的,其实不是,就是单纯的布尔变量,1,或者0。dp[i][j]代表:i个元素,任意选择是否"可"为j?可->1,不可->0,就这么简单。

class Solution {
public:
    bool canPartition(vector<int>& nums) 
    {
           //元素和相等——>数字集合的和等于1/2 sum
        if (accumulate(nums.begin(), nums.end(), 0) % 2 != 0 || nums.size() == 1)
            return 0;

        int target = accumulate(nums.begin(), nums.end(), 0) / 2;
        vector <vector<int>> dp(nums.size(), vector<int>(target + 1,0));
        //vector<vector<int>> vec(row, vector<int> (col,0)); -- 用 0 来初始化二维vector

        for (int i = 0; i < nums.size(); ++i) {
            dp[i][0] = 1;//均有方法可使得和为0
        }

        for (int j = 1; j <= target; ++j) {
            dp[0][j] = (j == nums[0]);
        }
        for (int i = 1; i < nums.size(); ++i)
        {
            for (int j = 1; j <= target; ++j)
            {
                dp[i][j] = dp[i - 1][j];
                if (j - nums[i] >= 0)
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]];
            }
            if (dp[i][target] == 1) 
                return 1;
        }
        return 0;
    }
};

notes

第一,vector二维数组的初始化问题。如果不手动初始化的话,似乎vector只会初始化一行,所以需要使用vector<vector<int>> vec(row, vector<int> (col,0)); -- 用 0 来初始化二维vector这一行代码,前面是row的数量,后面是col的数量。
第二,dp的初始化。第一次写的时候,初始化很想当然,理清思路以后初始化还是比较简单的。

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

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

相关文章

华侨大学主题模版

华侨大学主题模版 适用于 课程作业、实验报告、项目策划、毕业论文、毕设答辩... 这是一个非官方项目&#xff0c;仅供个人学习研究。 &#x1f680; 指南 &#x1f4d6; 仓库简介 该仓库提供了一系列适用于课程作业、实验报告、项目策划、毕业论文、毕设答辩等场景的华侨大…

API接口对电商平台有怎样的帮助?如何获取API接口?

API&#xff08;Application Programming Interface&#xff09;接口对电商平台有很多帮助&#xff0c;下面列举几点&#xff1a; 1.提高效率 API接口可以让电商平台的不同模块之间进行快速的数据交互&#xff0c;帮助平台实现更高效的业务处理。比如&#xff0c;在订单管理和…

牛客网学习之倒置字符串(详解fgets函数,如何读取含有空格的字符串)

题目要求&#xff1a; 过程分析&#xff1a;&#xff08;大致思路&#xff09; 具体代码&#xff1a; #include <stdio.h> #include <string.h> /*逆序字符串*/ void reverse(char* begin,char* end) {while (begin < end){char temp *begin;*begin *end;*en…

程序员的出路是什么?

做为一个程序员&#xff0c;工作了一定时间后&#xff0c;一定会有一个想法&#xff0c;那就是程序员能干多久&#xff0c;未来的发展方向是什么&#xff0c;更专业一点的说法是&#xff0c;职业规划到底是什么。 说实话&#xff0c; 我也仔细考虑过这个问题&#xff0c;偶尔也…

基于 HTTP Range 实现文件分片并发下载!

目录 前言 基础下载功能 进阶下载功能 单片下载 多片下载 浏览器发送预检&#xff08;preflight&#xff09;请求 express 不支持多段 range multipart/** 搭配 boundary** 分片下载功能 “只读的” ArrayBuffer 对象 DataView 子类 Uint8Array 操作二进制数据 Bl…

不愧是腾讯出来的,太厉害了...

前段时间公司缺人&#xff0c;也面了许多测试&#xff0c;一开始瞄准的就是中级水准&#xff0c;当然也没指望能来大牛&#xff0c;提供的薪资在15-20k这个范围&#xff0c;来面试的人有很多&#xff0c;但是平均水平真的让人很失望。看了简历很多上面都是写有4年工作经验&…

Go对Json的支持[encoding/json]

数据类型中转json的函数 基本数据转json Marshal使用以下与类型相关的默认编码: 布尔值编码为JSON布尔值。 浮点数、整数和数字值编码为JSON数字。 字符串值编码为JSON字符串&#xff0c;强制为有效的UTF-8; 用Unicode替换符文替换无效字节。 这样JSON就可以安全地嵌入到HTML …

2023年5月软考考试真题及答案汇总

2023上半年软考考试在5月27日-5月28日举行&#xff0c;为大家整理了各科目的考试真题及答案&#xff0c;可用于估分。&#xff08;会持续更新哦&#xff09; ​ 2023年上半年系统集成项目管理工程师上午题 1、在&#xff08; &#xff09;领域&#xff0c;我国还远未达到世界…

【数据结构】---几分钟简单几步学会手撕链式二叉树(中)

文章目录 前言&#x1f31f;一、二叉树链式结构的实现&#x1f30f;1.1 二叉树叶子节点个数&#x1f4ab;代码&#xff1a;&#x1f4ab;流程图&#xff1a; &#x1f30f;1.2 二叉树的高度&#x1f4ab;第一种写法(不支持)&#xff1a;&#x1f4d2;代码&#xff1a;&#x1f…

TCP协议的三次握手和四次挥手

完整的TCP内容&#xff0c;请参考RFC 9293 TCP协议为应用提供可靠的、有序的的字节流服务。TCP是面向连接的&#xff0c;提供了全双工的通信。TCP使用端口号来识别应用程序服务并在主机之间复用不同的流。 TCP header格式 TCP header也像IP header一样&#xff0c;在header中…

【Kafka】超详细介绍

文章目录 概念部署方案磁盘网络CPUpartition的数量 命令查看版本找kafka和zookeeper的ip/porttopic创建 topic查看get topic 列表get topic 详情 修改topic修改分区级别参数(如增加partition) 删除topic设置消息大小上限 生产查看生产生产消息 查看消费server 查看 offset查看积…

车载电子之汽车HUD技术

一、什么是HUD技术 HUD&#xff08;head up display抬头显示器&#xff09;是将重要信息显示在挡风玻璃上的一种显示系统&#xff0c;基本原理是&#xff1a;投影仪发出的光信息&#xff0c;经过一系列的折射、反射等投影到挡风玻璃上&#xff0c;人眼就能看到投射在上面的信息…

springboot+vue广场舞团系统(java项目源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的广场团舞系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌&a…

Jmeter接口测试-websocket测试

壹 Jmeter接口测试-websocket测试 测试之前的准备工作,需要websocket插件 方式一: 去github下载: https://github.com/maciejzaleski/JMeter-WebSocketSampler/wiki/Dependencies jetty-http-9.1.2.v20140210.jarjetty-io-9.1.2.v20140210.jarjetty-util-9.1.2.v20140210…

华为OD机试真题 Java 实现【云短信平台优惠活动】【2023Q1 200分】,附详细解题思路

一、题目描述 某云短信厂商&#xff0c;为庆祝国庆&#xff0c;推出充值优惠活动。 现在给出客户预算&#xff0c;和优惠售价序列&#xff0c;求最多可获得的短信总条数。 二、输入描述 第一行客户预算M&#xff0c;其中 0<M<1000000。 第二行给出售价表&#xff0c…

华为OD机试真题B卷 Java 实现【小朋友排队】

一、题目描述 小明今年升学到了小学1年级&#xff0c;来到新班级后&#xff0c;发现其他小朋友身高参差不齐&#xff0c;然后就想基于每个小朋友和自己的身高差&#xff0c;对他们进行排序&#xff0c;请帮他实现排序。 二、输入描述 第一行为正整数h和n。 0 < h < 2…

算法基础学习笔记——⑤离散化\区间和并

✨博主&#xff1a;命运之光 ✨专栏&#xff1a;算法基础学习 目录 ✨简述 特指整数离散化 &#x1f353;离散化模板&#xff1a; ✨区间和并 &#x1f353;区间和并模板&#xff1a; 前言&#xff1a;算法学习笔记记录日常分享&#xff0c;需要的看哈O(∩_∩)O&#xff0…

【树上差分+LCA】篮球杯 砍树

省赛的题现在来补 感觉什么都不会&#xff0c;已经要没了 题意&#xff1a; 思路&#xff1a; 考虑一条边&#xff0c;两端有两棵子树 有这样的性质&#xff1a; 这条边两端的结点的经过次数M 因此每加一个点对&#xff0c;都对其路径1 s[u]M时&#xff0c;与该点连着的…

大数据Doris(二十八):Broker Load通配符导入HDFS数据并指定列顺序

文章目录 Broker Load通配符导入HDFS数据并指定列顺序 一、创建Doris表 2、准备HDFS数据

Maven学习笔记(基础篇)22版

1. 概述部分 1. 什么是 Maven&#xff1f; 为什么要学习Maven&#xff1f; 管理规模庞大的 jar 包&#xff0c;需要专门工具。脱离 IDE 环境执行构建操作&#xff0c;需要专门工具。 1、构建 Java 项目开发过程中&#xff0c;构建指的是使用『原材料生产产品』的过程。 原…