【动态规划】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.hqwc.cn/news/105924.html

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

相关文章

小米汽车,能否在新能源汽车江湖站稳脚跟?

最近&#xff0c;圈内都在传小米汽车亦庄工厂已试生产近一个月&#xff0c;每周可产50辆样车&#xff0c;正在为首款新能源汽车量产做最后的准备。 此前的业绩交流会上&#xff0c;小米集团总裁卢伟冰透露&#xff0c;小米汽车结束了夏测且进展非常顺利&#xff0c;2024年上半…

前端开发纷繁复杂,是否有更高效的开发方式?

一、前言 此前&#xff0c;我曾跟大家聊到&#xff0c;低代码编程&#xff0c;在现阶段互联网业务疯狂增长的带动之下&#xff0c;被赋予了全新的使命和义务&#xff0c;即帮助开发者在前期以较低成本的方式&#xff0c;快速构建一个可投入市场的应用。 那么&#xff0c;有没有…

SpringBoot项目启动时预加载

SpringBoot项目启动时预加载 Spring Boot是一种流行的Java开发框架&#xff0c;它提供了许多方便的功能来简化应用程序的开发和部署。其中一个常见的需求是在Spring Boot应用程序启动时预加载一些数据或执行一些初始化操作。 1. CommandLineRunner 和 ApplicationRunner Spri…

串行通信协议

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、UART二、SPI二、IIC 前言 UART为异步串行通信&#xff0c;使用各自的时钟控制数据的发送和接受过程&#xff0c;不使用同步时钟&#xff0c;而是使用一些特…

平板触控笔哪款好用?好用的第三方apple pencil

而对于那些把ipad当做学习工具的人而言&#xff0c;苹果Pencil就成了必备品。但因为苹果Pencil太贵了&#xff0c;不少的学生们买不起。因此&#xff0c;最佳的选择还是平替电容笔&#xff0c;今天在这里整理了一些高性价比的电容笔&#xff01; 一、挑选电容笔的要点&#xf…

C语言学习系列-->字符函数和字符串函数

文章目录 一、字符函数1、字符分类函数2、字符转换函数 二、字符串函数1、strlen概述模拟实现 2、strcpy概述模拟实现 3、strcat概述模拟实现 3、strcmp概述模拟实现 4、有限制的字符串函数strncpystrncatstrncmp 4、strstr概述模拟实现 一、字符函数 1、字符分类函数 包含头…

常用消息中间件有哪些

RocketMQ 阿里开源&#xff0c;阿里参照kafka设计的&#xff0c;Java实现 能够保证严格的消息顺序 提供针对消息的过滤功能 提供丰富的消息拉取模式 高效的订阅者水平扩展能力 实时的消息订阅机制 亿级消息堆积能力 RabbitMQ Erlang实现&#xff0c;非常重量级&#xff0c;更适…

gitlab在项目中创建自己的分支的顺序操作,一整套流程

gitlab在项目中创建自己的分支的顺序操作&#xff0c;一整套流程 目录概述需求&#xff1a; 设计思路实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better…

三维模型OBJ格式轻量化压缩在大规模场景的加载和渲染的作用分析

三维模型OBJ格式轻量化压缩在大规模场景的加载和渲染的作用分析 OBJ格式是一种常用的三维模型文件格式&#xff0c;它存储了三维模型的几何信息和纹理坐标等相关属性。在大规模场景中加载和渲染三维模型时&#xff0c;OBJ格式的轻量化压缩对于提高性能和效率起到了重要的作用。…

MFC新建内部消息

提示&#xff1a;记录一下MFC新建内部消息的成功过程 文章目录 前言一、第一阶段二、第二阶段三、第三阶段总结 前言 先说一下基本情况&#xff0c;因为要在mapview上增加一个显示加载时间的功能。然后发现是要等加载完再显示时间&#xff0c;显示在主窗口。所以就是在子线程中…

YOLO DNF辅助教程完结

课程完结&#xff01;撒花、撒花、撒花 课程完结&#xff01;撒花、撒花、撒花 课程完结&#xff01;撒花、撒花、撒花 ​呕心沥血三个月&#xff0c;《利用人工智能做DNF游戏辅助》系列实战课程已完结&#xff0c;技术路线贯穿串口通信、目标检测、opencv特征匹配等前沿技术…

Git 版本回退 超神步骤

Git 版本回退 一. 背景 多版本分支开发&#xff0c;合并版本问题太多&#xff0c;需要回滚到某次版本。我的git客服端工具是 sourcetree 二.操作步骤 2.1 切到当前需要回退版本的分支 2.2 右击需要具体某一个分支&#xff0c;这个分支就是你想切到的分支版本&#xff0c;具体…