【动态规划】01背包问题

文章目录

  • 动态规划(背包问题)
    • 1. 01背包
    • 2. 分割等和子集
    • 3. 目标和
    • 4. 最后一块石头的重量 ||

动态规划(背包问题)

1. 01背包

题目链接

  1. 状态表示

    dp[i][j] 表示从前i个物品当中挑选,总体积不超过j,所有选法当中能挑选出来的最大价值

  2. 状态转移方程

    o8ohyy4czj-1692438261156.png

  3. 初始化

  4. 填表

  5. 返回值

AC代码:

#include <iostream>
#include <cstring>
const int N = 1010;
int n, V, v[N], w[N];
int dp[N][N];
int main()
{std::cin>> n >> V;for (int i = 1; i <= n; i++){std::cin>> v[i] >> w[i];}for (int i = 1; i <= n; i++){for (int j = 0; j <= V; j++){dp[i][j] = dp[i - 1][j];if (j >= v[i]) {dp[i][j] = std::max(dp[i][j], w[i] + dp[i - 1][j - v[i]]);}}}std::cout << dp[n][V] << std::endl;memset(dp, 0, sizeof(dp));for (int j = 1; j <= V; j++) dp[0][j] = -1;for (int i = 1; i <= n; i++){for (int j = 0; j <= V; j++){dp[i][j] = dp[i - 1][j];if (j >= v[i] && dp[i - 1][j - v[i]] != -1) {dp[i][j] = std::max(dp[i][j], w[i] + dp[i - 1][j - v[i]]);}}}std::cout << (dp[n][V] == -1 ? 0 : dp[n][V]) << std::endl;return 0;
}

空间优化:

利用滚动数组做空间上的优化,遍历顺序需要从右到左

不需要解释优化后的状态表示,以及状态转移方程

优化后代码:

#include <iostream>
#include <cstring>const int N = 1010;int n, V, v[N], w[N];
int dp[N];int main()
{std::cin>> n >> V;for (int i = 1; i <= n; i++){std::cin>> v[i] >> w[i];}for (int i = 1; i <= n; i++){for (int j = V; j >= v[i]; j--){dp[j] = std::max(dp[j], w[i] + dp[j - v[i]]);}}std::cout << dp[V] << std::endl;memset(dp, 0, sizeof(dp));for (int j = 1; j <= V; j++) dp[j] = -1;for (int i = 1; i <= n; i++){for (int j = V; j >= v[i]; j--){if (dp[j - v[i]] != -1) {dp[j] = std::max(dp[j], w[i] + dp[j - v[i]]);}}}std::cout << (dp[V] == -1 ? 0 : dp[V]) << std::endl;return 0;
}

2. 分割等和子集

题目链接

将一个数组分割成相同的两部分,就需要在整个数组里面找正好相等就可以。其实就是一个背包问题

  1. 状态表示

    dp[i][j]表示 0 到 i 区间内正好等于是否可以满足正好等于 j

  2. 状态转移方程

    image-20230820093108938

  3. 初始化

    第一列为true ,当目标是0是肯定可以满足

  4. 填表

  5. 返回值

AC代码:

class Solution 
{
public:bool canPartition(vector<int>& nums) {int n = nums.size();int sum = 0;for (auto x : nums) sum += x;if (sum % 2) return false;int aim = sum / 2;vector<vector<bool>> dp(n + 1, vector<bool>(aim + 1));for (int i = 0; i <= n; i++) dp[i][0] = true;for (int i = 1; i <= n; i++){for (int j = 1; j <= aim; j++){dp[i][j] = dp[i - 1][j];if (j >= nums[i - 1]) dp[i][j] = dp[i][j] || dp[i - 1][j - nums[i - 1]];}}return dp[n][aim];}
};

利用滚动数组进行优化:

class Solution 
{
public:bool canPartition(vector<int>& nums) {int n = nums.size();int sum = 0;for (auto x : nums) sum += x;if (sum % 2) return false;int aim = sum / 2;vector<bool> dp(aim + 1);dp[0] = true;for (int i = 1; i <= n; i++){for (int j = aim; j >= nums[i - 1]; j--){dp[j] = dp[j] || dp[j - nums[i - 1]];}}return dp[aim];}
};

3. 目标和

题目链接

分析题目,a 代表所有正数的和,b则代表所有负数的和

a - b = target a + b = sum 所以a = (target + sum) / 2

所以最终求的是是否可以让这个数是a

  1. 状态表示

    dp[i][j]表示从 i 个中选正好等于j 有多少中选法

  2. 状态转移方程

    nansoods64-1692755152155.png

  3. 初始化

  4. 填表

  5. 返回值

AC代码:

class Solution 
{
public:int findTargetSumWays(vector<int>& nums, int target) {int sum = 0;for (auto x : nums) sum += x;int aim = (sum + target) / 2;if (aim < 0 || (sum + target) % 2) return 0;int n = nums.size();vector<vector<int>> dp(n + 1, vector<int>(aim + 1));dp[0][0] = 1;for (int i = 1; i <= n; i++){for (int j = 0; j <= aim; j++){dp[i][j] = dp[i - 1][j];if (j >= nums[i - 1]) {dp[i][j] += dp[i - 1][j - nums[i - 1]];}}}return dp[n][aim];}
};

4. 最后一块石头的重量 ||

题目链接

这个题目就是在一个数组当中选一些数字,让这些数字尽可能的接近sum / 2

  1. 状态表示

    dp[i][j]表示 i 中选,总体积不超过j此时的最大和

  2. 状态转移方程

    image-20230823103352077

  3. 初始化

  4. 填表

  5. 返回值

AC代码:

class Solution {
public:int lastStoneWeightII(vector<int>& stones) {int sum = 0;for (auto x : stones) sum += x;int n = stones.size(), m = sum / 2;vector<vector<int>> dp(n + 1, vector<int>(m + 1));for (int i = 1; i <= n; i++) {for (int j = 0; j <= m; j++){dp[i][j] = dp[i - 1][j];if (j >= stones[i - 1]) {dp[i][j] = max(dp[i][j], dp[i - 1][j - stones[i - 1]] + stones[i - 1]);}}}return sum - 2 * dp[n][m];}
};
      dp[i][j] = dp[i - 1][j];if (j >= stones[i - 1]) {dp[i][j] = max(dp[i][j], dp[i - 1][j - stones[i - 1]] + stones[i - 1]);}}}return sum - 2 * dp[n][m];
}

};


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

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

相关文章

UDP协议

目录 一、UDP协议端格式 二、UDP的特点 一、UDP协议端格式 16位UDP长度&#xff0c;表示整个数据报&#xff08;UDP首部UDP数据&#xff09;的最大长度&#xff1b;如果校验和出错&#xff0c;就会直接丢弃 二、UDP的特点 UDP相对于TCP来说是相对简单的&#xff0c;但是在传输…

Redis:实现全局唯一id

&#xff08;笔记总结自《黑马点评》项目&#xff09; 一、全局ID生成器 全局ID生成器&#xff0c;是一种在分布式系统下用来生成全局唯一ID的工具&#xff0c;一般要满足下列特性&#xff1a; 二、原理 为了增加ID的安全性&#xff0c;我们可以不直接使用Redis自增的数值&…

C++学习第二十二天----函数

1.函数的参数以及局部变量 程序清单7.4&#xff1b; 27f4614 Kite/C和C - Gitee.com 2.函数和数组 程序清单7.5&#xff1b;函数参数是数组 233e36e Kite/C和C - Gitee.com 在c中&#xff0c;当且仅当用于函数头或函数原型中&#xff0c;int *arr 和int arr[ ]的含义相同…

Python文件读写模式

python操作文件 open的常用参数&#xff1a; 1.要读取的文件名字或者文件路径 2.文件打开的模式 r:只读模式 rb&#xff1a;以二进制的格式去打开文件 3.encoding&#xff1a;用来指定文件的编码格式&#xff08;使用rb的时候&#xff0c;不需要加该参数&#xff09; #打…

测试----计算机网络

文章目录 计算机网络的历史OSI/RM 协议TCP/IP协议IP地址 计算机网络的历史 50-60年代 内部通讯功能&#xff08;连接的是同一台主机&#xff0c;只能主机和终端之间通信&#xff0c;终端和终端之间的通讯只能依靠主机来传输&#xff09;60-70年代 主机和主机之间能通讯70年代-…

232 - Crossword Answers (UVA)

这道题因为我把puzzle打成了Puzzle&#xff0c;卡了我很久…………真的太无语了。 题目链接如下&#xff1a; Online Judge 我的代码如下&#xff1a; #include <cstdio> #include <cctype> #include <set> const int maxx 10;int r, c, kase, cnt, tem…

【狂神】SpringMVC笔记(一)之详细版

1.Restful 风格 概念&#xff1a; 实现方式&#xff1a; 使用PathVariable 在url相同的情况下&#xff0c;会根据请求方式的不同来执行不同的方法。 使用RestFull风格的好处&#xff1a;简洁、高效、安全 2、接受请求参数及数据回显 2.1、请求参数 方式一&#xff1a;这里…

chrome 谷歌浏览器 导出插件拓展和导入插件拓展

给同事部署 微软 RPA时&#xff0c;需要用到对应的chrome浏览器插件&#xff1b;谷歌浏览器没有外网是不能直接下载拓展弄了半小时后才弄好&#xff0c;竟发现没有现成的教程&#xff0c;遂补充&#xff1b; 如何打包导出 谷歌浏览器 地址栏敲 chrome://extensions/在对应的地…

分类预测 | Matlab实现基于LFDA-SVM局部费歇尔判别数据降维结合支持向量机的多输入分类预测

分类预测 | Matlab实现基于LFDA-SVM局部费歇尔判别数据降维结合支持向量机的多输入分类预测 目录 分类预测 | Matlab实现基于LFDA-SVM局部费歇尔判别数据降维结合支持向量机的多输入分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于局部费歇尔判别数据降维的L…

当前时代下的思维稀缺

关于稀缺&#xff0c;有专门的一本书来讲&#xff0c;但这里将的稀缺不是注意力的问题&#xff0c;而是我们的思考力。 互联网时代下&#xff0c;看似我们能够更轻松地、更迅速地获取到各种信息&#xff0c;每个时间碎片都被各类的讯息所填满&#xff0c;以至于睡觉就被感觉是…

总结/笔记-逻辑函数封装

逻辑函数拆分业务&#xff1a;将同一组件中独立的业务代码通过函数做封装处理&#xff0c;提高代码的可维护性。 步骤&#xff1a; 1. 命名函数&#xff1a;use业务名.js 2. 用函数封装业务逻辑 3. 函数内&#xff0c;return 数据、方法 4. 组件中 调用函数使用 // 封装业…

upload-labs 16/17关

16 将gif文件和包含一句话木马的php文件放在同一目录下&#xff0c;用cmd的copy命令将php文件整合进文件中。 可以看到最后一行包含了注入代码 将b1文件上传到服务器后&#xff0c;发现并未能正常执行代码&#xff0c;将上传后的文件下载到本地&#xff0c;打开后发现最后的代…

Swift学习内容精选(一)

Swift 可选(Optionals)类型 Swift 的可选&#xff08;Optional&#xff09;类型&#xff0c;用于处理值缺失的情况。可选表示"那儿有一个值&#xff0c;并且它等于 x "或者"那儿没有值"。 Swfit语言定义后缀&#xff1f;作为命名类型Optional的简写&…

二进制链表转整数

给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。 请你返回该链表所表示数字的 十进制值 。 示例 1&#xff1a; 输入&#xff1a;head [1,0,1] 输出&#xff1a;5 解释&#xff1a;二进制数 (101) 转化为十进…

OpenCV(二十六):边缘检测(二)

目录 1.Laplacian算子边缘检测 原理&#xff1a; Laplacian边缘检测函数Laplacian() 示例代码&#xff1a; 2.Canny算子边缘检测 原理&#xff1a; Canny算法函数Canny() 示例代码&#xff1a; 1.Laplacian算子边缘检测 原理&#xff1a; Laplacian算子的原理基于图像…

【Git-Exception】Git报错:fatal: unable to auto-detect email address

报错信息&#xff1a; *** Please tell me who you are. Run git config --global user.email “youexample.com” git config –global user.name “Your Name” to set your account’s default identity. Omit --global to set the identity only in this repository. fatal…

Prometheus+Grafana可视化监控【主机状态】

文章目录 一、介绍二、安装Prometheus三、安装Grafana四、Pronetheus和Grafana相关联五、监控服务器状态六、常见问题 一、介绍 Prometheus是一个开源的系统监控和报警系统&#xff0c;现在已经加入到CNCF基金会&#xff0c;成为继k8s之后第二个在CNCF托管的项目&#xff0c;在…

规范的企业开发常需要的配置文件-Python开发技巧XI

目录 Flake8 pyproject commitlint.config .pre-commit-config.yaml 触发时刻 意义 Flake8 Flake8 是一个用于检查 Python 代码风格和质量的工具。 对应.flake8文件 可以检查代码中的语法错误、风格问题和潜在的 bug。 &#xff08;1&#xff09;规范代码风格&#x…

【Leetcode-面试经典150题-day22】

目录 97. 交错字符串 97. 交错字符串 题意&#xff1a; 给定三个字符串 s1、s2、s3&#xff0c;请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下&#xff0c;其中每个字符串都会被分割成若干 非空 子字符串&#xff1a; s s1 s2 …

【Java基础篇 | 面向对象】—— 继承

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习JavaSE的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 继承允许一个类继承另一个…