Day42:动态规划 LeedCode 01背包 416. 分割等和子集

01背包

1.确定dp数组以及下标的含义

dp[i][j]的含义:从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

那么可以有两个方向推出来dp[i][j]

2.确定递推公式

  • 不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)
  • 放物品i:由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值,所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

3.初始化

dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。

如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。

dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。

那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。

当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。

4.确定遍历顺序

由递推公式dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);dp[i][j] 是由左上方数值推导出来

先遍历 物品还是先遍历背包重量呢?

其实都可以!!


46. 携带研究材料

时间限制:5.000S  空间限制:128MB

题目描述

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。 

小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。

输入描述

第一行包含两个正整数,第一个整数 M 代表研究材料的种类,第二个正整数 N,代表小明的行李空间。

第二行包含 M 个正整数,代表每种研究材料的所占空间。 

第三行包含 M 个正整数,代表每种研究材料的价值。

输出描述

输出一个整数,代表小明能够携带的研究材料的最大价值。

输入示例
6 1
2 2 3 1 5 2
2 3 1 5 4 3
输出示例
5
提示信息

小明能够携带 6 种研究材料,但是行李空间只有 1,而占用空间为 1 的研究材料价值为 5,所以最终答案输出 5。 

数据范围:
1 <= N <= 5000
1 <= M <= 5000
研究材料占用空间和价值都小于等于 1000

代码参考:

import java.util.*;
public class Main{
    public static void main(String[] args ){
        Scanner scanner=new Scanner(System.in);
        int m=scanner.nextInt();
        int n=scanner.nextInt();
        int[][] t=new int[2][m];
        for(int i=0;i<2;i++){
            for(int j=0;j<m;j++){
                t[i][j]=scanner.nextInt();
            }
        }
        int[][]dp=new int[m][n+1];
        //初始化
        for(int j=0;j<=n;j++){
            if(t[0][0]<=j){
                dp[0][j]=t[1][0];
            }
        }
        for(int i=1;i<m;i++){
            for(int j=1;j<=n;j++){
                if(j<t[0][i]) dp[i][j]=dp[i-1][j];
                else  dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-t[0][i]]+t[1][i]);
            }
        }
        System.out.println(dp[m-1][n]);
    }
}

 优化上面代码,把二维的dp[][]数组该为一维

在使用二维数组的时候,递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

dp数组的第i层只与第i-1层有关

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

与其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了

该为一维dp数组后,根据地推公式可得,dp[i]都是由其左边的数得到的,所以遍历顺序应该改为从右往左,这样才能让dp[j]利用到上一层的dp[j]

import java.util.*;
public class Main{
    public static void main(String[] args ){
        Scanner scanner=new Scanner(System.in);
        int m=scanner.nextInt();
        int n=scanner.nextInt();
        int[][] t=new int[2][m];
        for(int i=0;i<2;i++){
            for(int j=0;j<m;j++){
                t[i][j]=scanner.nextInt();
            }
        }
        int[]dp=new int[n+1];
        //初始化
        for(int j=0;j<=n;j++){
            if(t[0][0]<=j){
                dp[j]=t[1][0];
            }
        }
         for(int i=1;i<m;i++)
        for(int j=n;j>=0;j--){
            if(j>=t[0][i])
                dp[j]=Math.max(dp[j],dp[j-t[0][i]]+t[1][i]);
        }

        System.out.println(dp[n]);
    }
}

dp数组初始化可以统一为0,物品从0开始 开始遍历

import java.util.*;
public class Main{
    public static void main(String[] args ){
        Scanner scanner=new Scanner(System.in);
        int m=scanner.nextInt();
        int n=scanner.nextInt();
        int[][] t=new int[2][m];
        for(int i=0;i<2;i++){
            for(int j=0;j<m;j++){
                t[i][j]=scanner.nextInt();
            }
        }
        int[]dp=new int[n+1];
       
        //初始化dp[]都为0
         for(int i=0;i<m;i++)
        for(int j=n;j>=0;j--){
            if(j>=t[0][i])
                dp[j]=Math.max(dp[j],dp[j-t[0][i]]+t[1][i]);
        }

        System.out.println(dp[n]);
    }
}

 


416. 分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:

输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 100

思路:

用01背包问题解决该题,01背包要求一个物品最多取一次,跟这里的求子集的步骤一致,本题要求集合里能否出现总和为 sum / 2 的子集,即在01背包问题中的求价值为sum/2

只有确定了如下四点,才能把01背包问题套到本题上来。

  • 背包的体积为sum / 2
  • 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
  • 背包如果正好装满,说明找到了总和为 sum / 2 的子集。
  • 背包中每一个元素是不可重复放入。

动规五部曲分析如下:

1.确定dp数组以及下标的含义

dp[i]表示背包容量为i时的最大价值

本题中每一个元素的数值既是重量,也是价值。

所以 当 dp[target] == target 的时候,背包就装满了。

2.确定递推公式

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

3.dp数组如何初始化

如果题目给的价值都是正整数那么非0下标都初始化为0就可以了,如果题目给的价值有负数,那么非0下标就要初始化为负无穷。

4.确定遍历顺序

如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!

5.举例推导dp数组

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

 

 

 


 

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

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

相关文章

记一次Mysql数据库宕机This could be because you hit a bug.

Hi I’m Shendi 今天收到消息说所有软件不能用了&#xff0c;网页都打不开&#xff0c;遇到了问题&#xff0c;于是在这里记录一下 记一次Mysql数据库宕机This could be because you hit a bug. 起因 为了节省成本&#xff0c;对于小公司而言服务器数量通常不会太多&#xff…

网络安全学习路线-超详细

零基础小白&#xff0c;到就业&#xff01;入门到入土的网安学习路线&#xff01; 在各大平台搜的网安学习路线都太粗略了。。。。看不下去了&#xff01; 建议的学习顺序&#xff1a; 一、网络安全学习普法&#xff08;心里有个数&#xff0c;要进去坐几年&#xff01;&#x…

FRDM-MCXN947开发板之RGB灯

一、背景 RGB LED&#xff1a;通过红、绿、蓝三种颜色组合发光的LED&#xff0c;可以理解由三个不同发光属性的LED组成&#xff0c;这个是LCD平板显示原理的基础&#xff0c;一个LED相当于屏幕上面的一个像素 FRDM-MCXN947集成了一块RGB LED&#xff0c;它由三个GPIO口驱动&am…

2024 NTFS读写工具Tuxera NTFS for Mac 是如何进行下载、安装、激活的

本篇将为各位小伙伴们集中讲解一下NTFS读写工具Tuxera NTFS for Mac 是如何进行下载、安装、激活与换机的。 在数字化时代&#xff0c;数据交换和共享变得日益重要。然而&#xff0c;对于Mac用户来说&#xff0c;与Windows系统之间的文件交换可能会遇到一些挑战。这是因为Mac …

【Markdown】调整图片大小和对齐方式

插入图片 使用HTML: <img src"./xxx.png" width "xxx" height "xxx" />比如说我们插入一个图片&#xff0c;系统会自动帮我们生成一个图片链接 把这段链接插入即可 <img src"https://img-blog.csdnimg.cn/direct/66da1f6404…

大模型日报|今日必读的10篇大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.谷歌推出新型 Transformer 架构&#xff1a;反馈注意力就是工作记忆 虽然 Transformer 给深度学习带来了革命性的变化&#xff0c;但二次注意复杂性阻碍了其处理无限长输入的能力。 谷歌研究团队提出了一种新型 T…

《自动机理论、语言和计算导论》阅读笔记:p225-p260

《自动机理论、语言和计算导论》学习第 9 天&#xff0c;p225-p260总结&#xff0c;总计 26 页。 一、技术总结 1.pushdown automation(PDA&#xff0c;下推自动机) 2.DPDA Deterministic PDA(确定性下推自动机)。 二、英语总结 1.instantaneous (1)instant: adj. happi…

苹果电脑启动磁盘是什么意思 苹果电脑磁盘清理软件 mac找不到启动磁盘 启动磁盘没有足够的空间来进行分区

当你一早打开苹果电脑&#xff0c;结果系统突然提示&#xff1a; “启动磁盘已满&#xff0c;需要删除部分文件”。你会怎么办&#xff1f;如果你认为单纯靠清理废纸篓或者删除大型文件就能释放你的启动磁盘上的空间&#xff0c;那就大错特错了。其实苹果启动磁盘的清理技巧有很…

app测试系列-超详细的app测试攻略,一文带你学会移动端测试

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

模板初阶的学习

目录&#xff1a; 一&#xff1a;泛型模板 二&#xff1a;函数模板 三&#xff1a;类模板 1&#xff1a;泛型模板 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础。 以交换函数为列进行讲解&#xff1a; void Swap(…

【C++对于C语言的扩充】函数重载、引用以及内联函数

文章目录 &#x1f680;前言&#x1f680;函数重载注意&#xff1a;✈️为什么C可以实现函数重载&#xff0c;而C语言却不行呢&#xff1f; &#x1f680;引用✈️引用的特性✈️C中为什么要引入引用✈️引用与指针的区别 &#x1f680;内联函数✈️内联函数特性 &#x1f680;…

Python 序列化与反序列化

目录 1、基本概念 2、JSON模块 2.1、dumps() 与 loads() 函数 2.2、dump() 与 load() 函数 2.3、bool 、None 类型的序列化与反序列化 3、pickle模块 3.1、dumps() 与 loads() 函数 3.2、dump() 与 load() 函数 1、基本概念 说明&#xff1a;通过文件操作&#xff0c;…

移动硬盘盒支持PD充电:优势解析与实际应用探讨

随着科技的飞速发展&#xff0c;数据存储和传输的需求日益增长&#xff0c;移动硬盘盒作为便携式存储设备的重要载体&#xff0c;其功能和性能也在不断提升。近年来&#xff0c;越来越多的移动硬盘盒开始支持PD&#xff08;Power Delivery&#xff09;充电技术&#xff0c;这一…

案例研究|众乐邦将MeterSphere持续测试平台融入DevOps流水线

众乐邦网络科技有限公司&#xff08;以下简称为“众乐邦”&#xff09;是一家企业服务公司。其旗下的众乐邦灵活用工数字化薪税管理平台&#xff08;以下简称为灵活用工管理平台&#xff09;&#xff0c;以财税服务视角切入灵活用工场景&#xff0c;连接企业、灵活就业者和监管…

平台系统的微信支付服务突然不可用问题记录

背景 我们平台系统的微信支付突然不可用&#xff0c;用户点击支付都提示错误“系统繁忙”。 排查 查看日志&#xff0c;发现“支付聚合服务”调用“微信支付服务”的http请求返回read timeout&#xff0c;问题很显然出在“微信支付服务”。http请求报read timeout&#xff0…

全球顶级的低代码开发平台,你知道几个?

什么是低代码开发平台? 低码开发平台是一个应用程序,提供图形用户界面编程,从而以非常快的速度开发代码,减少了传统的编程工作。 这些工具有助于快速开发代码,最大限度地减少手工编码的努力。这些平台不仅有助于编码,而且还能快速安装和部署。 低码开发工具的好处 低代码平…

【JavaSE】你真的了解内部类吗?

前言 本篇会详细讲解内部类的四种形式&#xff0c;让你掌握内部类~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 内部类介绍 实例内部类 定义 调用 静态内部类 定义 调用 匿名内部类 定义和调用1 调用方法2 …

vs2019 - detected memory leak

文章目录 vs2019 - detected memory leak概述笔记vs2019 consolevs2019 MFC Dlg但是&#xff0c;工程大了之后&#xff0c;VS2019提示的就变了样整好的内存泄漏侦测头文件和实现my_debug_new_define.hmy_debug_new_define.cpp在所有.cpp文件入口处包含my_debug_new_define.h包含…

计算机系列之操作系统的系统

2、大话操作系统的启动 当按下开机键时&#xff0c;BIOS 就会开始执行 ​ BIOS 就是放在主板上 ROM 里面的一段程序。 ​ ROM Read Only Memory&#xff08;只能读取的内存&#xff09; ​ 所以 BIOS 在出厂的时候就可以直接写死在 ROM 里面。 ​ 每次开机的时候&#xff…

【数据结构与算法】之双向链表及其实现!

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 目录 1、双向链表的结构及概念 2、双向链表的实现 2.1 要实现的接口…