【代码随想录|动态规划背包问题】

news2024/12/23 17:35:02

一、背包问题分类

01背包:n种物品,每种物品只有一个

完全背包:n种物品,每种物品有无限个

多重背包:n种物品,每种物品的个数各不相同

二、01背包问题三道题

卡码网46题.携带研究材料(二维背包问题)

题目链接:46. 携带研究材料(第六期模拟笔试)

1.确定dp[i][j]含义: i 个物品,在背包容量为 j 时能得到的 最大价值

dp(n,vector<int>(bagweight+1,0));

这里的dp数组行坐标背包容量是从0开始遍历的,列坐标物品是从第一个物品开始遍历

2.递推公式:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);

看的时候一头雾水,慢慢整理,我感觉是dp[i][j]每个元素都有两个选择,取或者不取物品i,

不取的话:就是dp[i-1][j],代表我在当前的背包容量下,我还是只装前面一个物品,

取的话:就是dp[i-1][j-weight[i]]+value[i],我先把这个物品的需要的容量先空出来,然后加上i这个物品所能带给我的价值

然后我们进行比较,取还是不取带来的价值大,选大的那个

3.dp数组的初始化

例如

背包为0的时候,什么都装不下,所以dp[i][0]全为0,这个设置数组的时候就可以初始化为0,所以可以不管,然后看我背包容量为几的时候才能装下物品0

从第一个物品需要的容量开始到被背包容量结束初始化为第一个物品的价值

4.遍历顺序:从前向后,从上往下

5.(打印dp数组)

#include<vector>
#include<iostream>
using namespace std;
int main(){
    int n,bagweight;
    cin>>n>>bagweight;//n代表研究材料的种类(物品数量)
                      //bagweight代表小明的行李空间(背包最大重量)
    vector<int>weight(n,0);
    vector<int>value(n,0);
    for(int i=0;i<n;i++){
        cin>>weight[i];//每种研究材料的所占空间(每个物品所占重量)
    }
    for(int i=0;i<n;i++){
        cin>>value[i];//每种研究材料的价值(每个物品的价值)
    }
     vector<vector<int>> dp(n,vector<int>(bagweight+1,0));
    for(int j=weight[0];j<=bagweight;j++){
        dp[0][j]=value[0];
    }//直接从第一个物品需要的容量开始到被背包容量结束初始化为第一个物品的价值
    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[n-1][bagweight];
    return 0;
}

卡码网46题.携带研究材料(二维背包问题)

题目链接:46. 携带研究材料(第六期模拟笔试)

1.确定dp[i][j]含义:容量为j的背包,所背的物品价值可以最大为dp[j]。

其实就是二维数组转成一维,节省了空间复杂度,但是时间复杂度还是o(n^2)

2.递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

同样的

我感觉是dp[j]每个元素都有两个选择,取或者不取物品i,

不取的话:就是dp[j],因为这个一维数组我还没有更新,还是装的前面一个物品,

取的话:就是dp[j - weight[i]] + value[i],我先把这个物品的需要的容量先空出来,然后加上i这个物品所能带给我的价值

然后我们进行比较,取还是不取带来的价值大,选大的那个

3.dp数组的初始化

因为背包容量为0所背的物品的最大价值就是0,那么dp[0]就应该是0,其他的为了方便就初始化为0就行。

4.遍历顺序:

外层循环从前往后遍历每一个物品,内层循环从后往前,遍历背包的容量

之所以内层是从后往前进行遍历,是因为我从前面往后面遍历的话,我就是已经选了这个物品了,然后我后面在用前面的值的话,就会再重复选这个物品,但是如果我倒序遍历的话,我用到的前一个值就是还没选的值,进行更新就不会选择到前面的物品。

做的时候一直没想明白为什么二维dp数组的i是从1开始,而一维i是从0开始

思考了一下感觉是 

二维 DP 数组i 从 1 开始,是因为第 0 行通常用于初始化,表示没有物品的情况。

一维 DP 数组dp[0] 表示背包容量为 0 时的最大价值,所以初始化时 dp[0] = 0,并且 j 从 0 开始遍历。

二维数组i从1开始是因为0行已经被初始化了,而一维数组从0开始是因为我们初始化也要在这个一维数组里面进行,所以从0开始

5.(打印dp数组)

#include<vector>
#include<iostream>
using namespace std;
int main(){
    int n,bagweight;
    cin>>n>>bagweight;
    vector<int>weight(n,0);
    vector<int>value(n,0);
    for(int i=0;i<n;i++){
        cin>>weight[i];//通过物品的数量一一对应每个物品的重量
    }
    for(int i=0;i<n;i++){//通过物品的数量一一对应每个物品的价值
        cin>>value[i];
    }
     vector<int>dp(bagweight+1,0);
     for(int i=0;i<n;i++){
         for(int j=bagweight;j>=weight[i];j--){
             dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
         }
     }
     
     cout<<dp[bagweight];
    return 0;
}

416.分割等和子集

题目链接:416. 分割等和子集 - 力扣(LeetCode)

这道题是要看两个子集是否相等,把这个集合所有的元素加起来除以2就是我一个子集需要的达到的价值,思路就是把它看成价值和容量相等的一维背包问题,

我觉得就是把书包容量设置为一个子集的大小,大乱炖,胡乱的取物品在书包里,如果到最后背包价值等于一个子集的价值,那另一个子集肯定也是这个价值(因为如果背包价值不等于一个子集的价值,两个子集相加是sum是固定的,就说明另一个子集要小一点,那两个子集肯定就不相等了)

然后我们就可以着手实现他了,因为把书包容量和价值看成一样的,我们就先遍历物品,选择拿或者不拿,递推公式就为:

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

 其他的思路跟一维背包问题还是一样的

最开始一直没搞懂dp数组的大小怎么设置得那么大都是10001了,后来慢慢理发现

是因为传入的每个数每个数最大为100,传入的数的数量不超过200因为要算每个数总和sum/2为dp的大小,算出来大小为10000,又因为dp从0开始所以为10001

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        vector<int>dp(10001,0);
        int sum=0;
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
        }
        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;
        else return false;
    }
};

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

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

相关文章

第1章 命题逻辑

2024年12月22日 一稿 1.1 现代逻辑学的基本研究方法 1.2 命题及其表示法 1.2.1 命题的概念 定义1.1 命题是一个可以判断真假的陈述句。 1.2.2 联结词 非 与 或 蕴含 等价 1.3 命题公式与语句形式化 1.3.1 命题公式的定义 1.3.2 公式的层次 1.3.3 语句形式化 1…

Unity-Editor扩展GUI基本实现一个可拖拉放的格子列表

短短几百行代码,好吧,又是“参考”了国外的月亮 操作,还真地挺自然的。。。。。。国外的实现有点小牛 拖拉,增加+ 一个Element 鼠标左键长按,可以出提示 鼠标右键,清除Element, 有点小bug,不是很自然地完全清除, using System.Collections; using System.Collecti…

解决vscode ssh远程连接服务器一直卡在下载 vscode server问题

目录 方法1&#xff1a;使用科学上网 方法2&#xff1a;手动下载 方法3 在使用vscode使用ssh远程连接服务器时&#xff0c;一直卡在下载"vscode 服务器"阶段&#xff0c;但MobaXterm可以正常连接服务器&#xff0c;大概率是网络问题&#xff0c;解决方法如下: 方…

重拾设计模式--外观模式

文章目录 外观模式&#xff08;Facade Pattern&#xff09;概述定义 外观模式UML图作用 外观模式的结构C 代码示例1C代码示例2总结 外观模式&#xff08;Facade Pattern&#xff09;概述 定义 外观模式是一种结构型设计模式&#xff0c;它为子系统中的一组接口提供了一个统一…

jvm栈帧结构

JVM(Java虚拟机)中的虚拟机栈是线程私有的,用于支持Java虚拟机进行方法调用和方法执行。而栈帧(Stack Frame)则是虚拟机栈的基本元素,每一个方法从调用开始至执行结束的整个过程,都对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。栈帧的内部结构主要包括以下几个部分:…

2009 ~ 2019 年 408【计算机网络】大题解析

2009 年 路由算法&#xff08;9’&#xff09; 讲解视频推荐&#xff1a;【BOK408真题讲解-2009年&#xff08;催更就退网版&#xff09;】 某网络拓扑如下图所示&#xff0c;路由器 R1 通过接口 E1 、E2 分别连接局域网 1 、局域网 2 &#xff0c;通过接口 L0 连接路由器 R2 &…

Flamingo论文介绍:把视觉特征向语言模型看齐

今天介绍一篇经典的多模态论文&#xff0c;来自NeurIPS 2022的《Flamingo: a Visual Language Model for Few-Shot Learning》 &#xff0c;论文地址&#xff1a;https://arxiv.org/pdf/2103.00020 文章目录 一、Motivate二、Method三、模块细节&#xff1a;Perceiver Resampl…

【VSCode】常用插件汇总

1 Path Autocomplete&#xff08;路径提示的插件&#xff09; 步骤一&#xff1a;在vscode的扩展搜索中直接搜索Path Autocomplete&#xff0c;直接安装 步骤二&#xff1a;配置 配置 VS Code settings.json "path-autocomplete.pathMappings": {"": &q…

STM32F103 | Embedded IDE03 - 使用OpenOCD在STM32F103项目时出现下载固件失败

导言 在上一篇备忘录介绍使用OpenOCD的stlink-v2.cfg接口下载固件&#xff0c;在STM32F407的项目上很顺利。但是&#xff0c;在stm32f103上会出现下载失败。 在网上搜了一下&#xff0c;这位博主的文章解决了这个问题: https://www.iotword.com/26738.html 一、修改stm32f1x.c…

易语言 OCR 文字识别

一.引言 文字识别&#xff0c;也称为光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;&#xff0c;是一种将不同形式的文档&#xff08;如扫描的纸质文档、PDF文件或数字相机拍摄的图片&#xff09;中的文字转换成可编辑和可搜索的数据的技术。随着技…

Linux 网络维护相关命令简介

目录 零. 概要一. ping二. ip命令2.1 ip address2.2 ip route2.3 ip neighbour 三. traceroute四. DNS查询4.1 nslookup4.2 dig 五. ss 查看网络连接状态 零. 概要 ⏹在Linux系统中有2套用于网络管理的工具集 net-tools 早期网络管理的主要工具集&#xff0c;缺乏对 IPv6、网…

vscode中同时运行两个python文件(不用安装插件)

如何在vscode中同时运行两个python文件呢&#xff1f;今天在工作中遇到了这个问题。 查了网上的方法是安装coder runner插件&#xff0c;后来发现自身就有这个功能。所以记录一下,方便后续查找: 这是我的第一个文件&#xff0c;点击右上角的运行旁边的小箭头&#xff0c;有一…

matlab绘图时设置左、右坐标轴为不同颜色

目录 一、需求描述 二、实现方法 一、需求描述 当图中存在两条曲线&#xff0c;需要对两条曲线进行分别描述时&#xff0c;应设置左、右坐标轴为不同颜色&#xff0c;并设置刻度线&#xff0c;且坐标轴颜色需要和曲线颜色相同。 二、实现方法 2.1、实现目标&#xff1a; 1…

解决Apache/2.4.39 (Win64) PHP/7.2.18 Server at localhost Port 80问题

配置一下apache里面的配置文件&#xff1a;httpd.conf 和 httpd.vhosts.conf httpd.conf httpd-vhosts.conf 重启服务 展示&#xff1a; 浏览器中中文乱码问题&#xff1a;

RunCam WiFiLink连接手机图传测试

RunCam WiFiLink中文手册从这里下载 一、摄像头端 1.连接天线&#xff08;易忘&#xff09; 2.打开摄像头前面的盖子&#xff08;易忘&#xff09; 3.接上直流电源&#xff0c;红线为正&#xff0c;黑线为负 4.直流电源设置电压为14v&#xff0c;电流为3.15A&#xff0c; 通…

用JAVA做了一个登录窗体练习

目 录 说明运行后的效果代码 说明 做了一个登录窗体作为练习&#xff0c;分享给大家&#xff0c;其中涉及到窗体、图板、随机数等内容&#xff0c;为了方便和我一样的小白可以看的比较明白&#xff0c;所以尽量详细的标注了注释&#xff0c;希望能帮到同样在学习路上的朋友 运…

《开启微服务之旅:Spring Boot 从入门到实践》(一)

Spring Boot Spring Boot 入门 Spring Boot 简介&#xff08;脚手架&#xff09; 简化Spring应用开发的一个框架&#xff1b; 整个Spring技术栈的一个大整合&#xff1b; J2EE开发的一站式解决方案&#xff1b; 优点&#xff1a;快速创建独立运行的spring项目以及与主流…

springboot466大学生就业服务平台(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统大学生就业服务平台信息管理难度大&#xff0c;容错率低&…

ROS1入门教程2:主题发布和订阅

一、创建发布者 创建源文件publisher.cpp&#xff0c;并写入以下内容&#xff1a; #include <iostream>#include "ros/ros.h" #include "std_msgs/String.h"int main(int argc, char* argv[]) {std::string nodeName "publisher"; // 节…

WALN无线网络的创建和管理-二层组网

⼆层组⽹配置过程&#xff1a; 在AC上配置DHCP 1&#xff0c;先将AP划分到管理vlan&#xff0c;并在相关链路上运⾏vlan数据通过 2&#xff0c;在AC上创建管理vlan的vlanif接⼝&#xff0c;配置IP参数 3&#xff0c;在AC上配置DHCP服务器 4&#xff0c;指定WLAN管理vlan&am…