算法训练第30天|46. 携带研究材料(01背包问题)|416. 分割等和子集

news2024/9/20 22:50:46

先讲一下01背包问题:

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

这道题目如果使用暴力解法,即回溯法来做的话,时间复杂度很大,O(2^{n}),n表示物品的数量。

如果使用动态规划的方法来做:

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

        我们需要使用二维数组的两个维度分别表示,物品 和 背包容量,即dp[i][j]。
        i 来表示物品、j表示背包容量

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

2、确定递推公式

        对于递推公式,首先我们要明确有哪些方向可以推导出 dp[i][j]

        这里我们dp[1][4]的状态来举例:

        dp[1][4] 来自于 放物品1 ,还是不放物品1。

        如果不放物品1, 那么背包的价值应该是 dp[0][4] 即容量为4的背包,只放物品0的情况。        

        如果物品1, 那么背包要先留出物品1的容量,目前容量是4,物品1 需要重量为3,此时背包剩下容量为1。容量为1,只考虑放物品0 的最大价值是 dp[0][1],这个值我们之前就计算过。

        所以 放物品1 的情况 = dp[0][1] + 物品1 的价值

        两种情况,分别是放物品1 和 不放物品1,我们要取最大值

        以上过程,抽象化如下:

  • 不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。

  • 放物品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数组如何初始化

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

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

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

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

        3.其他下标应该初始化多少?dp[i][j] 是由左上方数值推导出来了,那么 其他下标初始为什么数值都可以,因为都会被覆盖。

4、确定遍历顺序

        先遍历物品还是先遍历背包,其实都可以

5、举例推导dp数组


KamaCoder 46. 携带研究材料 (01背包问题)

题目链接:01背包问题

题目讲解:代码随想录

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

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

输入描述

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

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

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

输出描述

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

这道题目,M可以看成是物体中重量,N可以看成物体的价值。

package main

import(
    "fmt"
)

func max(a, b int) int{
    if a < b{
        a = b
    }
    return a
}

func main(){
    // 定义 物品种类,和背包大小
    var itemKinds, bagWeight int
    fmt.Scan(&itemKinds, &bagWeight)
    
    // 定义 每种物品所占背包的大小
    // 定义 每种物品的价值
    var weights, values []int
    weights = make([]int, itemKinds)
    values = make([]int, itemKinds)
    
    for i := 0; i < itemKinds; i++{
        fmt.Scan(&weights[i])
    }
    
    for i := 0; i < itemKinds; i++{
        fmt.Scan(&values[i])
    }
    
    // dp[i][j] -- 0--i物品任意选(选/不选),行李空间为j时 最大价值
    // dp[i][j] = dp[i-1][j] (不选物品i) , 选i dp[i-1][j-weight[i]] + values[i])
    dp := make([][]int, itemKinds)
    for i := 0; i < itemKinds; i++{
        dp[i] = make([]int, bagWeight+1)
    }
    
    
    // 初始化dp,当背包容量为0时,放不进任何物品,所以肯定为0
    // 对第一个物品,如果背包容量小于第一个物品的weight,则
    // 放不进;背包容量大于等于第一个物品的weight,则直接放第一个物品
    for j := weights[0]; j <= bagWeight; j++{
        dp[0][j] = values[0]
    }
    
    // 开始遍历,对每一物品,遍历背包容量
    for i := 1; i < itemKinds; i++{
        for j := 1; j <= bagWeight; j++{
            if j < weights[i]{ // 物品i的大小比当前背包容量大,物品i不放入背包
                dp[i][j] = dp[i-1][j]
            }else{ // 物品i放入背包中
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-weights[i]] + values[i])
            }
        }
    }
    fmt.Println(dp[itemKinds-1][bagWeight])
}

LeetCode 416. 分割等和子集

题目链接:416. 分割等和子集

题目讲解:代码随想录

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

  • 背包的大小为sum / 2
  • 物品 相当于集合里的元素,重量为元素的数值,价值也为元素的数值
func canPartition(nums []int) bool {
    sum := 0
    for _, num := range nums{
        sum += num
    }

    // 如果 nums 的总和为奇数,则不可能平分成两个子集
    if sum % 2 == 1{
        return false
    }

    target := sum / 2
    dp := make([][]int, len(nums))
    for i := 0; i < len(nums); i++{
        dp[i] = make([]int, target+1)
    }

    for j := nums[0]; j <= target; j++{
        dp[0][j] = nums[0]
    }

    for i := 1; i < len(nums); i++{
        for j := 0; j <= target; 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])
            }
        }
    }

    return dp[len(nums)-1][target] == target
}

func max(a, b int)int{
    if a > b{
        return a
    }
    return b
}

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

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

相关文章

Transformer简明笔记:文本翻译

Bert和gpt都是基于transformer的&#xff0c;在此之前流行的是rnn&#xff0c;复杂度有限且效率不高&#xff0c;容易受到文本长度的限制。 项目地址:https://github.com/lansinuote/Transformer_Example b站视频&#xff1a;https://www.bilibili.com/video/BV19Y411b7qx?p9&…

Java项目: 基于SpringBoot+mysql旅游网站管理系统分前后台(含源码+数据库+开题报告+PPT+毕业论文)

一、项目简介 本项目是一套基于SpringBootmysql旅游网站管理系统分前后台 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作…

【java入门】JDK的下载安装与配置,最新最详细教程!

&#x1f680; 个人简介&#xff1a;某大型国企资深软件开发工程师&#xff0c;信息系统项目管理师、CSDN优质创作者、阿里云专家博主、华为云云享专家&#xff0c;分享前端后端相关技术与工作常见问题~ &#x1f49f; 作 者&#xff1a;码喽的自我修养&#x1f970; &#…

创意微型学生机床工具——金属车床

劳技课程是实施劳动与技术教育的主要途径&#xff0c;具有基础性、实践性、综合性和创新性等特点。它不仅是国家课程、地方课程和校本课程的统一体&#xff0c;还是基础教育课程体系中的重要一环。 劳技课程强调学生的动手操作能力和实践体验&#xff0c;通过具体的技术活动和劳…

IP的SSL证书的申请及配置方式

随着互联网技术的发展&#xff0c;数据安全变得越来越重要。HTTPS协议因其提供的加密传输能力而成为现代Web通信的标准。实现HTTPS的关键组件之一就是SSL/TLS证书&#xff0c;它为网站提供了一层保护&#xff0c;确保客户端与服务器之间的数据传输是加密的。本文将指导您如何为…

NSSCTF刷题

[NISACTF 2022]checkin 1.在选中nisactf的时候&#xff0c;注释里面的内容也被标记了 2.复制到010editer中发现存在不可见的字符 3.我们选择实际的参名和字符串&#xff0c;并转为url编码格式 4.得到最后的payload&#xff0c;传参得到flag ahahahahajitanglailo&%E2%80%…

当敏捷开发遇上AI

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【ESP32 IDF】WS2812B灯驱动

WS2812B灯驱动 1. 简单描述2. 驱动过程3.主函数添加驱动程序 1. 简单描述 开发环境为 IDF5.2.2采用乐鑫官方组件库 组件库地址 &#xff1a; https://components.espressif.com/components/espressif/led_strip/versions/2.5.5 2. 驱动过程 复制led_strip组件命令 在自己项目…

密钥分发与公钥认证:保障网络通信的安全

在网络通信中&#xff0c;密钥的安全分发和公钥的有效认证是确保系统安全的关键。本文将为基础小白介绍密钥分发与公钥认证的基本概念和实际应用&#xff0c;帮助大家更好地理解这些技术如何保障我们的网络通信安全。 1. 密钥分发与公钥认证的背景 由于密码算法是公开的&…

数仓基础(九):各大公司实时数仓实践

文章目录 各大公司实时数仓实践 一、网易实时数仓实践 二、汽车之家实时数仓实践 三、顺丰实时数仓实践 四、​​​​​​​腾讯实时数仓实践 五、​​​​​​​​​​​​​​滴滴实时数仓实践 ​​​​​​​​​​​​​​各大公司实时数仓实践 一、网易实时数仓实践…

OpenHarmony编译开发:hiperf应用优化调试命令行工具实践

简介 hiperf 是 OpenHarmony 为开发人员提供的用于调试的命令行工具&#xff0c;用于抓取特定程序或者系统的性能数据,类似内核的 perf 工具&#xff0c;该工具支持在 Windows/Linux/Mac 等操作系统上运行。 架构 目录 /developtools/hiperf ├── demo # demo 程序 │ …

单片机-串口通信(二)

目录 一、串口概念 1.相关概念&#xff1a; 按数据传输方式分类&#xff1a; 按时钟分类 二、STM32F103ZET6中串口 USART特性&#xff1a; NRZ数据格式&#xff1a; 三、配置串口通信 查看硬件原理图 软件配置流程 USART相关的寄存器 新建my_usart1.c和my_usart1.h …

Python 中 9 种关键文件类型你了解几个?

当你遇到名称以 .ipynb、.pyi、.pyc 等结尾的 Python 文件时&#xff0c;你是否会感到困惑&#xff1f; 你想知道所有这些文件类型之间的区别吗&#xff1f;今天就和大家一起了解所有这些 Python 文件类型。&#x1f642; .py文件&#xff1a;标准 Python 源代码 不用多说&a…

C++:this指针详解

目录 一、this指针 二、C和C语言实现Stack对比 一、this指针 • Date类中有 Init 与 Print 两个成员函数&#xff0c;函数体中没有关于不同对象的区分&#xff0c;那当d1调用Init和 Print函数时&#xff0c;该函数是如何知道应该访问的是d1对象还是d2对象呢&#xff1f;那么这…

【蔡英丽医生】颈动脉斑块:认识它,预防它,应对它

在我们日常的健康检查中&#xff0c;颈动脉斑块这个词可能会不经意间跃入眼帘&#xff0c;尤其是对于40岁以上的朋友们来说&#xff0c;它的出现率更是居高不下。据调查数据显示&#xff0c;我国40岁以上人群中&#xff0c;颈动脉斑块的检出率超过40%&#xff0c;而60岁以上的人…

【UE5】控件蓝图——树视图(TreeView)的基本使用

目录 前言 效果 步骤 一、显示根节点 二、显示子节点 前言 我们在视口中添加1个方块&#xff0c;2个球体&#xff0c;5个圆柱 它们在大纲视图中的层级关系如下&#xff0c;那么如何将这种层级关系显示在树视图中是本篇文章要解决的问题。 效果 步骤 一、显示根节点 1…

【靶场】Pikachu—XSS Cross-Site Scripting(前五关)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【靶场】Pikachu—XSS Cross-Site Scripting&#xff08;前五关&#xff09; 第一关 反射型xss(get)第二关 反射型xss(post)第三关…

WeSiGJ的系列文章目录

文章目录 Cbasic 面试基础知识系列 23种 设计模式[创建式模式Creative Mode][结构型模式Structural pattern][行为模式Behavioral patterns] 关于作者支持作者 C basic 面试基础知识系列 abstractassertbit_fieldbit_operationCFeaturesconstdecltype 多态double_colon 冒号e…

宝塔官网下载地址

宝塔官网下载地址

启服云专利管理系统 高效管理创新成果

在知识经济时代&#xff0c;专利作为企业的核心竞争力和创新成果的重要载体&#xff0c;其管理效率与保护水平直接关系到企业的市场竞争力与未来发展。启服云管理软件作为一款集智能化、高效化、安全化于一体的为科技服务和知识产权领域设计的SaaS解决方案&#xff0c;旨在帮助…