代码随想录算法训练营第三十六天|01背包问题 二维 ,01背包问题 一维 ,416. 分割等和子集

news2025/1/23 2:06:57

背包理论基础

01 背包(二维)

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

背包最大重量为4。

物品为:

重量价值
物品0115
物品1320
物品2430

问背包能背的物品最大价值是多少?

思路:依然是动态规划。

解决:动态规划五步曲

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

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

        2.确定递推公式;

                考虑dp[i][j]是如何推导过来;

                ①加入第i件物品;

                        加入第i件物品后,相较于第i-1个物品,加入第i件物品后价值总和就等于dp[i-1][j-weight[i]]+value[i]

                ②第i件物品加入重量超标,不加入;

                        不加入价值总和就是放入第i-1个物品后价值总和:dp[i-1][j]

        所以dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])

        3.确定dp数组初始化;

        首先当j=0时,也就是书包最大重量为0时,dp[i][0]=0;其次只放物品0时,背包价值总和都是15,所以dp[0][j]=15(j>weight[0])。注意这里容量要大于第一个物品的重量。

        4.确定遍历顺序;

        遍历顺序肯定是从左向右,从上到下,最后遍历到右下角。

        5.举例推导dp数组。

        

代码:

void test_2_wei_bag_problem1() {
    vector<int> weight={1,3,4};
    vector<int> value={15,20,30};
    int bagweight = 4;
    vector<vector<int>> dp(weight.size(),vector<int>(bagweight+1,0));//i是物品数量,j是背包容量
    //初始化
    for(int j=weight[0];j<=bagweight;j++){
        dp[0][j]=value[0];
    }
// weight数组的大小 就是物品个数
    for(int i = 1; i < weight.size(); i++) { // 遍历物品
        for(int j = 0; j <= bagweight; 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]);

        }
    }

    cout << dp[weight.size() - 1][bagweight] << endl;
int main() {
    test_2_wei_bag_problem1();
}

 01 背包(一维)

例子:背包最大重量为4。

物品为:

重量价值
物品0115
物品1320
物品2430

问背包能背的物品最大价值是多少?

思路:对于背包问题其实状态都是可以压缩的。

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

其实可以发现如果把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[j](一维数组,也可以理解是一个滚动数组)。

解决:动态规划五步曲

        1.确定dp[j]的含义;

         dp[j]表示容量为j的背包,能背的最大价值。

        2.确定递推公式;

        dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);这里还是一样可以选择放i物品或者不放。

        3.确定dp初始化;

        最开始j=0时候,装不了物品。dp[0]=0;

        4.确定遍历顺序;

        举一个例子:物品0的重量weight[0] = 1,价值value[0] = 15

        如果正序遍历

        dp[1] = dp[1 - weight[0]] + value[0] = 15

        dp[2] = dp[2 - weight[0]] + value[0] = 30

        此时dp[2]就已经是30了,意味着物品0,被放入了两次,所以不能正序遍历。        

        倒序就是先算dp[2]

        dp[2] = dp[2 - weight[0]] + value[0] = 15 (dp数组已经都初始化为0)

        dp[1] = dp[1 - weight[0]] + value[0] = 15

        所以从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了

        5.举例推导公式。

代码:

void test_1_wei_bag_problem() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagWeight = 4;

    // 初始化
    vector<int> dp(bagWeight + 1, 0);
    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]);
        }
    }
    cout << dp[bagWeight] << endl;
}

int main() {
    test_1_wei_bag_problem();
}

416. 分割等和子集 - 力扣(LeetCode)

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

示例 1:

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

示例 2:

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

思路:这个问题如何转化成背包问题?最好的结果就是分成两个子集和相等,既然和相等,那么子集的和就是总和的一半,也就是说,从nums数组种取出元素,能够满足和等于总和的一半,那么结果就是true。那这里背包容量就是总和的一半,物品的价值就是元素数值,物品重量可以说每个都是1,也可以不用管

解决:动态规划五步曲:

        1.确定dp[i]的含义;

        j表示背包总容量,这里相当于目标值,从目标值递减遍历;背的最大重量为dp[j],当dp[j]等于目标值时说明可以分割成两个子集。

        2.确定递推公式;

        dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])。

        3.确定dp初始化;

        初始化和一维数组一样,都设置为0。

        4.确定遍历顺序;

        遍历顺序从大到小,防止重复放入。

        5.举例推导公式。

代码:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
        }
        vector<int> dp(10001, 0);
        if(sum%2==1){
            return false;
        }
        int target=sum/2;
        for(int i=0;i<nums.size();i++){
            for(int j=target;j>=nums[i];j--){//注意遍历顺序
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        if (dp[target] == target) return true;
        return false;
    }
};

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

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

相关文章

Segment Anything--SAM自动标注(一)

文章目录 开场白基本组件搞事情从来不是一帆风顺复旦方案分支回归主线 开场白 老样子先说一下为什么我会看到这篇文章。答案是“自动标注”。 这个事情是这样&#xff0c;自动驾驶不光需要做目标检测任务也需要语义分割的信息给到后处理。当然现在做自动驾驶都在往BEV方案上靠…

IntelliJ IDEA 之初体验

文章目录 第一步&#xff1a;下载与安装 IntelliJ IDEA1&#xff09;官网下载2&#xff09;选择那种安装包3&#xff09;开始下载4&#xff09;解压 第二步&#xff1a;启动 IntelliJ IDEA第三步&#xff1a;创建第一个 Java 项目第四步&#xff1a;运行第一个 Java 程序1&…

【408】计算机学科专业基础 - 计算机组成原理

一、计算机系统概述 【复习提示】 本章是组成原理的概述&#xff0c;考查时易针对有关概念或性能指标出选择题&#xff0c;也可能综合后续章节的内容出有关性能分析的综合题。掌握本章的基本概念&#xff0c;是学好后续章节的基础。部分知识点在初学时理解不深刻也无须担忧&am…

智能优化算法应用:基于变色龙算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于变色龙算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于变色龙算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.变色龙算法4.实验参数设定5.算法结果6.参考文献7.…

十五、FreeRTOS之FreeRTOS信号量

本节需要掌握以下内容&#xff1a; 1&#xff0c;信号量的简介&#xff08;了解&#xff09; 2&#xff0c;二值信号量&#xff08;熟悉&#xff09; 3&#xff0c;二值信号量实验&#xff08;掌握&#xff09; 4&#xff0c;计数型信号量&#xff08;熟悉&#xff09; 5&…

Linux--程序地址空间

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 [TOC](文章目录) 一、程序地址空间回顾 我们在讲C语言的时候&#xff0c;老师给大家画过这样的空间布局…

Transformer在视觉的应用

文章目录 Vison TransformerSwin TransformerVisual Attention Network Vison Transformer transformer 在 cv 中最重要的算法 Linear Projection of Flattened Patches 对于标准的Transformer模块&#xff0c;要求输入的是token&#xff08;向量&#xff09;序列&#xff…

鸿蒙4.0开发笔记之ArkTS语法基础之应用生命周期与页面中组件的生命周期(十六)

文章目录 一、应用生命周期二、生命周期函数定义三、生命周期五函数练习 一、应用生命周期 1、定义 应用生命周期就是代表了一个HarmonyOS应用中所有页面从创建、开启到销毁等过程的全生命周期。查看路径如下&#xff1a; Project/entry/src/main/ets/entryability/EntryAbili…

vue elementUI 上传非空验证

<el-form-item label"照片" prop"staffImg"><template v-slot:label><span v-show"!rules.staffImg[0].required"style"color: #ff4949;margin-right: 4px;">*</span><span>照片</span></temp…

【JavaWeb学习笔记】6 - Tomcat

项目代码 零、在线文档 Apache Tomcat 8 (8.0.53) - Documentation Index WEB开发 1. WEB,在英语中web表示网/网络资源(页面&#xff0c;图片,css,js)意思&#xff0c;它用于表示WEB服务器(主机)供浏览器访问的资源 2. WEB服务器(主机)上供外界访问的Web资源分为: 静态web…

LeetCode 每日一题 Day 4

2477. 到达首都的最少油耗 给你一棵 n 个节点的树&#xff08;一个无向、连通、无环图&#xff09;&#xff0c;每个节点表示一个城市&#xff0c;编号从 0 到 n - 1 &#xff0c;且恰好有 n - 1 条路。0 是首都。给你一个二维整数数组 roads &#xff0c;其中 roads[i] [ai,…

Myblog01-基于基本的javaWeb设计实现

目录 一、项目概述&#xff1a; 应用技术&#xff1a; 接口实现&#xff1a; 数据库建表&#xff0c;sql脚本&#xff1a; 页面展示&#xff1a;登陆页面 项目源码&#xff1a;myblog01: 初版的个人博客项目-使用基本的javaWeb (gitee.com) 二、对博客系统进行测试 总结 一、项…

怎么给文章润色?文章润色怎么收费?

文章润色&#xff0c;指的是在原有文章基础上&#xff0c;对语言表达、逻辑结构、风格等方面进行优化调整&#xff0c;以提高文章的阅读体验和质量。 润色不同于修改&#xff0c;修改主要针对文章中的错误&#xff0c;如语法、拼写、标点等&#xff1b;而润色则是对文章的整体…

网页抓取为什么要使用http代理?

目录 前言 一、网页抓取的定义 二、使用HTTP代理的原因 1. 防止IP被封锁 2. 提高访问速度 3. 保护隐私 4. 突破地域限制 三、使用Python进行网页抓取并使用HTTP代理 1. 安装必要的Python模块 3. 获取网页源代码 4. 解析网页内容 总结 前言 网页抓取是指从互联网中…

如何解决syntaxerror: more than 255 arguments 报错

如何解决syntaxerror: more than 255 arguments 报错 问题背景解释解决方案 问题背景 今天拼接特征的时候&#xff0c;突然代码报错syntaxerror: more than 255 arguments &#xff0c;看了一下感觉这个报错非常有意思&#xff0c;估计平时也是没机会碰到&#xff0c;和大家分…

课题学习(十五)----阅读《测斜仪旋转姿态测量信号处理方法》论文

一、 论文内容 1.1 摘要 为准确测量旋转钻井时的钻具姿态&#xff0c;提出了一种新的信号处理方法。测斜仪旋转时&#xff0c;垂直于其旋转轴方向加速度计的输出信号中重力加速度信号分量具有周期性特征&#xff0c;以及非周期性离心加速度分量频率低于重力加速度信号分量频率…

ROS-ROS通信机制-参数服务器

文章目录 一、基础理论知识二、C实现三、Python实现 一、基础理论知识 参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器&#xff0c;可以将数据存储在该容器中&#xff0c;被不同的节点调用&#xff0c;当然不同的节点…

【GAMES101】二维变换和齐次坐标

这几天都在抽空学OpenGL、敲leetcode和看games&#xff0c;这里留点笔记给以后复习 games101第一节课在吹水&#xff0c;第二节课讲了线性代数的入门知识&#xff0c;比较简单&#xff0c;这里稍微回顾一下重点&#xff0c;然后开始讲第三节课的二维变换和齐次坐标 目录 向量…

前端CSS(层叠样式表)总结

CSS2总结 一、CSS基础 1. CSS简介 CSS 的全称为&#xff1a;层叠样式表 ( Cascading Style Sheets ) 。CSS 也是一种标记语言&#xff0c;用于给 HTML 结构设置样式&#xff0c;例如&#xff1a;文字大小、颜色、元素宽高等等。 简单理解&#xff1a; CSS 可以美化…