LeetCode动态规划经典题目(九):0-1背包问题

news2024/11/13 18:45:11

学习目标:

0-1背包问题


学习内容:

9. LeetCode416. 分割等和子集icon-default.png?t=MBR7https://leetcode.cn/problems/partition-equal-subset-sum/

10. LeetCode1049. 最后一块石头的重量 IIicon-default.png?t=MBR7https://leetcode.cn/problems/last-stone-weight-ii/


学习产出:

独立解决以上题目,并懂得举一反三。

目录

8. 背包问题

9. LeetCode416. 分割等和子集

10. LeetCode1049. 最后一块石头的重量 II


8. 背包问题

0-1背包:
有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

思路:
1.动态规划二维表:
dp[i][j]:任意取0~i的物品,放假容量为j的背包里,价值总和最大值。
2.转移方程:
对于物品i:
  2.1取物品i:dp[i][j]=dp[i-1][j](其实是背包当前容量无法再放入物品i)
  2.2不取物品i:dp[i][j]=dp[i-1][j-weight[i]]+value[i](j-weight[i]是为物品i腾出空间)
综上:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
3.初始化dp:
由转移方程可知,新dp值由左上角推得,所以先初始化第0行和第0列

完整代码:
int maxValueInBag(vector<int>weight,vector<int>value,int capacity){
    //dp[i][j]:任意取0~i的物品,放假容量为j的背包里,价值总和最大值。
    vector<vector<int>>dp(weight.size(),vector<int>(capacity+1));
    
    //初始化dp
    for(int i=0;i<weight.size();i++){
        //容量为0的情况下,什么都放不了,价值是0
        dp[i][0]=0;
    }
    for(int j=weight[0];j<=capacity;j++){
        dp[0][j]=value[0];
    }
    
    //完善dp
    for(int i=1;i<weight.size();i++){
        for(int j=1;j<=capacity;j++){
            if(j<weight[i])dp[i][j]=dp[i-1][j];
            else dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
            //腾出空间放入新物品的总价值不一定比不放入新物品的总价值大
        }
    }
    return dp[weight.size()-1][capacity];
}

优化空间效率:滚动数组
int maxValueInBag(vector<int>weight,vector<int>value,int capacity){
    vector<int>dp(capacity+1);
    //初始化dp
    for(int j=weight[0];j<=capacity;j++){
        dp[j]=value[0];
    }
    for(int i=1;i<weight.size();i++){
        for(int j=capacity;j>=weight[i];j--){//因为依赖左上角值,所以从右往左遍历
            //如果当前j<weight[i],j--后必然也小于weight[i],直接结束内层循环即可
            dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
        }
    }
    return dp[capacity];
}

9. LeetCode416. 分割等和子集

思路:
转换成0-1背包问题,只要dp中有值等于sum/2的,就return true

1. dp[i][j]:从0~i下标中组合起来的值不超过j的最大值
2. dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i])
3. 初始化dp
    
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;//nums总和
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
        }
        if(sum%2==1)return false;//奇数无法二分

        //dp[i][j]:从0~i下标中组合起来的值不超过j的最大值
        vector<vector<int>>dp(nums.size(),vector<int>((sum/2)+1));
        
        //初始化dp
        for(int i=0;i<nums.size();i++){
            dp[i][0]=0;
        }
        for(int j=nums[0];j<=sum/2;j++){
            dp[0][j]=nums[0];
        }

        //完善dp
        for(int i=1;i<nums.size();i++){
            for(int j=1;j<=sum/2;j++){
                if(j<nums[i])dp[i][j]=dp[i-1][j];
                else dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i]);
            }
        }
        //在整个nums数组(下标0~nums.size()-1)中,是否有能组成sum/2的集合
        return dp[nums.size()-1][sum/2]==sum/2;
    }
};

优化空间效率:滚动数组
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;//nums总和
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
        }

        if(sum%2==1)return false;

        vector<int>dp((sum/2)+1);
        for(int j=nums[0];j<=sum/2;j++){
            dp[j]=nums[0];
        }
        for(int i=1;i<nums.size();i++){
            for(int j=sum/2;j>=nums[i];j--){
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[sum/2]==sum/2;
    }
};

10. LeetCode1049. 最后一块石头的重量 II

思路:
可把问题转变成将石头分成两堆且质量和尽可能相同,即靠近sum/2,这样两堆石头互相磨损完后,剩余石头质量最小。

1. dp[i][j]:从0~i的石头中,取最靠近质量j的石头组合的质量和
2. dp[i][j]=max(dp[i-1][j],dp[i-1][j-stones[i]]+stones[i])
3. 初始化dp

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum=0;
        for(int i=0;i<stones.size();i++){
            sum+=stones[i];
        }
        int target=(sum+1)/2;//取较大的中间值,因为大的包含小的

        //dp[i][j]:从0~i的石头中,取最靠近质量j的石头组合的质量和
        vector<vector<int>>dp(stones.size(),vector<int>(target+1));

        //初始化dp
        for(int i=0;i<stones.size();i++){
            dp[i][0]=0;
        }
        for(int j=stones[0];j<=target;j++){
            dp[0][j]=stones[0];
        }

        //完善dp
        for(int i=1;i<stones.size();i++){
            for(int j=1;j<=target;j++){
                if(j<stones[i])dp[i][j]=dp[i-1][j];
                else dp[i][j]=max(dp[i-1][j],dp[i-1][j-stones[i]]+stones[i]);
            }
        }
        return abs((sum-dp[stones.size()-1][target])-dp[stones.size()-1][target]);
    }
};

优化空间效率:滚动数组
class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum=0;
        for(int i=0;i<stones.size();i++){
            sum+=stones[i];
        }
        int target=(sum+1)/2;

        vector<int>dp(target+1);
        for(int j=stones[0];j<=target;j++){
            dp[j]=stones[0];
        }

        for(int i=1;i<stones.size();i++){
            for(int j=target;j>=stones[i];j--){
                dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        return abs((sum-dp[target])-dp[target]);
    }
};

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

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

相关文章

Makefile学习⑦:编译动态链接库和静态库

Makefile学习⑦&#xff1a;编译动态库和静态库 编译链接动态库 动态链接库名词解释&#xff1a; 动态&#xff1a;运行时才去加载&#xff0c;动态加载 链接&#xff1a;指库文件和二进制程序分离&#xff0c;用某种特殊手段维护两者之间的关系 库 &#xff1a;库文件&#…

8、条件语句

目录 一、简单的if条件语句 二、if…else语句 三、if…else if多分支语句 四、switch多分支语句 一、简单的if条件语句 语法如下&#xff1a; 布尔表达式&#xff1a;必要参数&#xff0c;表示最后返回的结果必须是一个布尔值。它可以是一个单纯的布尔变量或常量&#xff…

IntelliJ IDEA 插件推荐

本篇主要统计了一些 Idea 的常用插件 分享一下 感谢作者zzp google-java-format 作用 代码格式化风格。 插件官网 google-java-format - plugin for IntelliJ IDEs | JetBrains 使用说明 插件安装完成后需要到Preferences->Other Settings->google-java-format Set…

供应商管理难点在哪 SRM供应商系统助推企业提升管理水平

在如今&#xff0c;对于需求企业来说&#xff0c;要保证企业内部的正常生产或科研工作等过程的不间断&#xff0c;就需要有一批可靠的供应商定期提供必需的物资供应。而供应商管理的最终目的就是根据采购需求来建立一个稳定可靠的供应商管理队伍&#xff0c;为企业提供高质量的…

【Leetcode每日一题】27. 原地移除元素|神级理解双指针

博主简介&#xff1a;努力学习的预备程序媛一枚~博主主页&#xff1a; 是瑶瑶子啦所属专栏: LeetCode每日一题–进击大厂 目录题目描述题目分析&#xff1a;代码实现补充训练--验证代码实现题目描述 链接: 27. 移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原…

Java开发实现图书管理系统

本文用Java代码实现图书代码管理系统&#xff0c;有些地方可能会有纰漏&#xff0c;希望各位大佬鉴赏&#xff01;&#xff01; 文章目录 文章目录 一、Java实现图书管理系统 1.1创建book包 二、创建图书管理系统的操作包 2.1创建Operation接口 三、创建User包 3.1创建User类 四…

并发编程学习(七):线程活跃性:死锁、活锁、饥饿

线程活跃性 是指代码有限&#xff0c;但由于某种原因&#xff0c;导致线程一直未执行完成。 1、死锁 指两个或两个以上的进程&#xff08;或线程&#xff09;在执行过程中&#xff0c;因争夺资源而造成的一种互相等待的现象&#xff0c;若无外力作用&#xff0c;它们都将无法推…

四元数学习笔记(一):初识四元数

1 四元数的定义 1.1 为什么要使用四元数 旋转向量用 9 个量来描述 3 个自由度的旋转&#xff0c;具有冗余性&#xff1b;欧拉角和旋转向量是紧凑的&#xff0c;但是具有奇异性。事实上&#xff0c;我们找不到不带奇异性的向量描述方式。 回忆之前学习过的复数&#xff0c;我…

强化学习笔记:基于策略的学习之策略迭代(python实现)

目录 1. 前言 2. 算法流程 3. 代码及仿真结果 3.1 class PolicyIterationPlanner() 3.2 测试代码 3.3 运行结果 3.3.1 价值估计结果 3.3.2 策略迭代得到的最终策略 1. 前言 在强化学习中&#xff0c;根据是否依赖于&#xff08;环境的&#xff09;模型&#xff0c;可以分…

OAK相机与树莓派

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

机器人中的数值优化之修正阻尼牛顿法

本文ppt来自深蓝学院《机器人中的数值优化》 目录 1 Newtons Method 2 Pratical Newtons Method 1 Newtons Method 当我们引入函数的二阶信息就考虑到了curvature info&#xff0c;这里先对函数进行泰勒展开&#xff0c;取二阶近似&#xff0c;对近似后的函数取最优解&#…

springboot 线程池

为什么要使用线程池 使用线程池之后&#xff0c;不需要频繁的去创建和销毁线程&#xff08;比如项目中手动创建线程&#xff0c;new Thread 类&#xff0c;我们可以把创建和销毁的线程的过程去掉&#xff09;&#xff0c;从而让线程得到重复的使用。并且可以对线程进行统一的管…

手把手教你用 Python 搭建一个图像分类器

深度学习是使用人工神经网络进行机器学习的一个子集&#xff0c;目前已经被证明在图像分类方面非常强大。 尽管这些算法的内部工作在数学上是严格的&#xff0c;但 Python 库(比如 keras)使这些问题对我们所有人都可以接近。 在本文中&#xff0c;我将介绍一个简单的图像分类…

机器人中的数值优化之最速下降法

本文ppt来自深蓝学院《机器人中的数值优化》 目录 1 迭代方向 2 步长的选择 3 Armijo condition 4 非精确线搜索的优势 1 迭代方向 梯度方向是函数上升最快的方向&#xff0c;而负梯度方向则是函数下降最快的方向&#xff0c;因此最速下降法就是以负梯度方向为迭代方向…

二叉树的构造和相关功能的代码实现及解析

目录 一.二叉树类的定义 二.构造二叉树&#xff08;构造函数&#xff09; 三.为二叉树插入节点(insert_value) 四.移除根节点(remove_root,lchild_leaf) 五.移除二叉树中的某值(remove,remove_value) 六.清空二叉树 七.前、中、后序遍历 一.二叉树类的定义 二叉树类的定…

Django入门学习-了解基本模块

目录 MVT设计了解 认识MVT 实际操作 Template&#xff1a; View: 路由配置 Model: 默认的后台管理模块 初始化admin模块 应用中Admin注册 MVT设计了解 认识MVT Django的web设计模型是MVT&#xff1a; Model&#xff1a;数据存储层&#xff0c;处理所有数据相关的业…

idea+ApifoxUploader+Apifox真是内外双修,香

前言 最近部门为整合后端组、前端组、测试组、需求组、产品组等组之间的工作流程&#xff0c;旨在提高协调与高效&#xff0c;其中之一就是希望开发组&#xff08;后端、前端&#xff09;开发的接口能及时更新&#xff0c;测试组能做接口测试&#xff0c;后期方便出文档&#x…

大公司为什么禁止SpringBoot项目使用Tomcat?

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

【2】burpsuite屏蔽浏览器无用流量包方法

0x01 问题描述经常会使用火狐或者谷歌去burpsuite对站点进行测试&#xff0c;但是在测试的过程中burpsuite经常抓到火狐浏览器自身的数据包或者其他无用的数据包&#xff0c;这就对我们工作的效率大有影响&#xff0c;所以这里来告诉大家如何解决此类问题。0x02 问题复现访问网…

星环科技数据治理与数据价值评估实践分享

数据价值评估背景 自2015年8月国务院《促进大数据发展行动纲要》提出“数据已成为国家基础性战略资源”以来&#xff0c;我国出台了诸多政策和法案&#xff0c;推进数据的发展和数据要素的资产化。 2019年10月&#xff0c;第十九届四中全会关于《推进国家治理体系和治理能力现…