代码随想录第37天|动态规划

01背包理论基础

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
参考
请添加图片描述

01背包: 每个物品只有一个, 只要选或不选两个选项

暴力解法: 回溯法枚举

  1. dp[i][j]: i 表示 0 ~ i 的物品, j 表示容量, 数值表示当前的最大价值
  2. 递推公式: max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i])
  3. 初始化: j = 0 时, 无法放任何有价值的物品, dp[i][0] = 0. i = 0时, 当空间 j 大于 物体0的价值时, 才能放该物品
  4. 遍历顺序: 由于是从左上和正上方推导, 所以先遍历背包或遍历物品都可

当 i 放进去时,物品集就被分成两部分 1~i-1 和 i
若将 i 放进去,那么就把 j 空间中的 w[i] 占据, 剩下 j-w[i] 的空间给前面 i-1 ,
那么只要这时候前面 i-1 在 j-w[i] 空间里构造出最大价值, dp[i-1][j-w[i]],再加上此时放入的i的价值v[i],就是dp[i][j]
请添加图片描述

#include<bits/stdc++.h>
using namespace std;
int main() {
    int M, N;
    cin >> M;
    cin >> N;
    
    vector<int> weight;
    vector<int> value;
    
    for (int i = 0; i < M; i++) {
        int tem;
        cin >> tem;
        weight.push_back(tem);
    }
    
    for (int i = 0; i < M; i++) {
        int tem;
        cin >> tem;
        value.push_back(tem);
    }
 
//dp[i][j] 物品为i, j为重量 
//i索引范围[0 ~ M-1], 大小为 M
//j索引范围[0 ~ N]], 大小为 N + 1
	vector<vector<int>> dp(M, vector<int>(N + 1, 0));

    for (int j = 0; j <= N; j++) {
        if (j >= weight[0])
            dp[0][j] = value[0];
    } 

    for (int i = 1; i < M; i++) {
        for (int j = 1; j <= N; j++) { //注意取 =
            if (j - weight[i] >= 0) {
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
            }
            else {
                dp[i][j] = dp[i - 1][j];
            }
            
        }
    }
    cout << dp[M - 1][N] << endl;
}

01背包理论基础(滚动数组)

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

二维数组的递推公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
二维压缩成一维的递推公式: dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);//其中j是表背包容量

二维改为一维的方法:
请添加图片描述
请添加图片描述

正序遍历背包容量时, 会出现重复相加的情况, 图中为物品0不断的被累加
请添加图片描述
倒序遍历背包容量时, 由于会把本次物品的价值先加上, 价值一定比为加之前的大(dp[0~3]一定比dp[4]小), 所以不会出现重复累计的情况
请添加图片描述

#include<bits/stdc++.h>
using namespace std;

int main() {
    int M;//种类
    int N;//空间
    cin >> M;
    cin >> N;
    
    vector<int> weight(M, 0);
    vector<int> value(M, 0);
    
    for (int i = 0; i < M; i++) {
        cin >> weight[i];
    }
    for (int i = 0; i < M; i++) {
        cin >> value[i];
    }
    
    vector<int> dp(N + 1, 0);
    
    for (int i = 0; i < M; i++) {
        for (int j = N; j >=0 ; j--) {
            if (j - weight[i] >= 0) {
                dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
            } else {
                dp[j] = dp[j];
            }
            
        }
    }
    cout << dp[N] << endl;
}

416. 分割等和子集

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
在这里插入图片描述
参考

思路: 回溯法 (超时)

class Solution {
public:
    bool myoperator(int target, int sum , vector<int>& nums, int index) {
        if (sum >= target) {
            return sum == target? true : false;
        }

        bool res = false;
        for (int i = index; i < nums.size(); i++) {
            res = myoperator(target, sum + nums[i], nums, i + 1);
            if (res == true) return true;
        }
        return false;
    }
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }
        if (sum % 2 == 1) return false;
        else return myoperator(sum/2, 0, nums, 0);
    }
};

思路: 01背包问题 - 每个元素只能放入一次

  1. dp[j] : 容量为j, 最大价值为dp[j], 在本题中容量和价值相同
  2. 递推公式:
  3. dp数组如何初始化
  4. 遍历顺序

能抽象成01背包最大值的原因:
5. 物品的重量和价值是相同的, dp[sum/2] 的最大值 value <= (sum/2)
6. 所以当 sum == value 时, 代表找到了一个元素

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }

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

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

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

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

相关文章

Python从0到100(三十三):xpath和lxml类库

1. 为什么要学习xpath和lxml lxml是一款高性能的 Python HTML/XML 解析器&#xff0c;我们可以利用XPath&#xff0c;来快速的定位特定元素以及获取节点信息 2. 什么是xpath XPath&#xff0c;全称为XML Path Language&#xff0c;是一种用于在XML文档中进行导航和数据提取的…

相机网线RJ45连接器双端带线5米8芯绿色网线注塑成型

相机网线RJ45连接器双端带线5米8芯绿色网线注塑成型&#xff0c;这款网线采用了环保的绿色材质&#xff0c;线长5米&#xff0c;足够满足大多数拍摄场景的需求。更重要的是&#xff0c;它采用了8芯设计&#xff0c;保证了数据传输的稳定性和高速性。在接口方面&#xff0c;它采…

JAVA:常用的算法指南

请关注微信公众号&#xff1a;拾荒的小海螺 博客地址&#xff1a;http://lsk-ww.cn/ 1、简述 在软件开发过程中&#xff0c;算法扮演着关键的角色。它们用于解决各种问题&#xff0c;从数据处理到搜索、排序等。本文将介绍几种常见的算法及其 Java 实现&#xff0c;包括排序算…

云计算【第一阶段(24)】Linux文件系统与日志分析

一、文件与存储系统的inode与block 1.1、硬盘存储 最小存储单位&#xff1a;扇区(sector) 每个扇区大小&#xff1a;512字节 1.2、文件存取 最小存取单位&#xff1a;块(block)连续八个扇区组成&#xff1a;块(block) 每个块大小&#xff1a;4K文件数据&#xff1a;实际数据…

“论云上自动化运维及其应用”写作框架,软考高级论文,系统架构设计师论文

论文真题 云上自动化运维是传统IT运维和DevOps的延伸&#xff0c;通过云原生架构实现运维的再进化。云上自动化运维可以有效帮助企业降低IT运维成本&#xff0c;提升系统的灵活度&#xff0c;以及系统的交付速度&#xff0c;增强系统的可靠性&#xff0c;构建更加安全、可信、…

电脑怎么录屏幕视频带声音?2种方法教会你

在数字时代的浪潮中&#xff0c;电脑屏幕视频录制已经成为一项潮流且实用的技能。无论是为了创作短视频、分享游戏过程&#xff0c;还是为了记录在线会议或教程&#xff0c;电脑录屏都是非常重要的功能。但是不少的人都会遇上录制好的视频没有声音的困境&#xff0c;面对这种情…

matrix-breakout-2-morpheus靶场

1 信息收集 1.1 主机发现 arp-scan -l 1.2 端口与服务扫描 发现开放22、80、81端口 2 访问服务 2.1 访问80端口 查看源代码 2.2 访问81端口 3 目录扫描 3.1 dirsearch目录扫描 dirsearch -u 192.168.1.14 发现robots.txt文件和javascript文件 访问文件 http://192.168…

HarmonyOS Next开发学习手册——显示图片 (Image)

开发者经常需要在应用中显示一些图片&#xff0c;例如&#xff1a;按钮中的icon、网络图片、本地图片等。在应用中显示图片需要使用Image组件实现&#xff0c;Image支持多种图片格式&#xff0c;包括png、jpg、bmp、svg和gif&#xff0c;具体用法请参考 Image 组件。 Image通过…

CS-隐藏防朔源-数据转发-iptables(Linux自带的防火墙)

免责声明:本文仅做技术交流与学习... 目录 准备环境: 1-iptables转发机设置转发: 2-CS服务器配置iptables服务器的IP 准备环境: 两台外网服务器. --iptables服务器就是做一个中转...封了中转就没了... 1-iptables转发机设置转发: iptables -I INPUT -p tcp -m tcp --dport 8…

【K8s】专题六(3):Kubernetes 稳定性之自动扩缩容

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 一、基本介绍 在 Kubernetes 中&#xff0c;自动扩缩容是一种动态调整集群资源&#xff0c;以灵活…

Linux基础篇-文件句柄数修改

目录 文件句柄数修改修改最大限制用户级的修改系统级的修改 文件句柄数修改 linux最大打开文件句柄数&#xff0c;即打开文件数最大限制&#xff0c;就是规定的单个进程能够打开的最大文件句柄数量&#xff08;Socket连接也算在里面&#xff0c;默认大小1024&#xff09; liu…

Fluent在Linux环境导入文本文件报错解决

问题描述 同样的文本文件&#xff08;如Profile文件、Chemkin反应机理文件等&#xff09;&#xff0c;Fluent在Windows环境中可正常读取和运算&#xff0c;但是在Linux环境中导入会出错。 Linux中&#xff0c;Fluent读取Chemkin文件报错 问题原因 可能原因之一&#xff1a;换…

交叉编译 tcpdump libpcap

文章目录 交叉编译 tcpdump & libpcap概述源码下载交叉编译 libpcap交叉编译 tcpdump 交叉编译 tcpdump & libpcap 概述 tcpdump 是一个强大的命令行包分析器&#xff0c;libpcap 是一个可移植的用于网络流量捕获的 C/C 库。tcpdump 依赖于 libpcap 库&#xff0c;同…

基于IMX8MPlus SMARC核心板的便携式床旁超声诊断仪应用解决方案

医学的高速发展&#xff0c;使得超声仪器得到了广泛的普及&#xff0c;便携式的床旁超声诊断仪&#xff0c;不仅满足临床医学对可视化、便携式、智能化的需求&#xff0c;还能满足基层患者随时随地快速筛查的需求。 便携式的床旁超声诊断仪&#xff0c;移动灵活方便&#xff0c…

检索增强生成RAG系列3--RAG优化之文档处理

在上一章中罗列了对RAG准确度的几个重要关键点&#xff0c;主要包括2方面&#xff0c;这一章就针对其中一方面&#xff0c;来做详细的讲解以及其解决方案。 目录 1 文档解析1.1 文档解析工具1.2 实战经验1.3 代码演示 2 文档分块2.1 分块算法2.2 实战经验2.3 代码演示 3 文档e…

OmniViD: A Generative Framework for Universal Video Understanding

标题&#xff1a;OmniViD:通用视频理解的生成框架 源文链接&#xff1a;https://openaccess.thecvf.com/content/CVPR2024/papers/Wang_OmniViD_A_Generative_Framework_for_Universal_Video_Understanding_CVPR_2024_paper.pdfhttps://openaccess.thecvf.com/content/CVPR202…

HarmonyOS Next开发学习手册——文本输入 (TextInput/TextArea)

TextInput、TextArea是输入框组件&#xff0c;通常用于响应用户的输入操作&#xff0c;比如评论区的输入、聊天框的输入、表格的输入等&#xff0c;也可以结合其它组件构建功能页面&#xff0c;例如登录注册页面。具体用法请参考 TextInput 、 TextArea 。 创建输入框 TextIn…

优化数据库字段使用位运算-php语言示例

背景&#xff1a;一个会员有三个状态&#xff0c;A、B、C&#xff0c;其中一个人可以为 A、B、C、AB&#xff1b;之前数据表结构加了三个字段is_a、is_b、is_c; 本人实在不想这样粗糙的实现需求&#xff0c;遂决定用位运算优化。 上代码&#xff1a; 位运算可以用来处理状态值…

注塑机压铸机比例泵PQ阀放大器

比例泵技术在注塑机和压铸机中的应用&#xff0c;主要通过调节液压泵的排量和压力&#xff0c;来实现对设备工作性能的优化和节能。比例泵技术的核心在于其能够根据实际需求&#xff0c;精确地控制液压系统的压力和流量。这一点对于注塑机和压铸机来说尤为重要&#xff0c;因为…

【面试系列】信息安全分析师高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…