代码随想录训练营30-动态规划3

一、0/1背包问题

参考博客,主要注意以下几个方面:

1 背包问题要素: 背包容积、物品价值、物品体积

2 dp含义,dp[j]表示为j体积下,最大的物品价值。

3 遍历顺序,如果是二维写法,可以不关心顺序,但是如果是一维写法,需要关心遍历顺序

4 初始化值,需要根据dp定义含义做初始化定义。

二、416 分割等和子集

主要是怎么思考,去和01背包问题联系起来:

首先,dp[j]代表什么?容量为j的背包,所背的物品价值最大可以为dp[j]。dp[j]表示背包总容量(所能装的总重量)是j,放进物品后背包的最大重量为dp[j]。换句话说,在此题目中,背包容积和价值都是num[x]。所以状态公式为:

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

考虑初始化情况,当dp[0]应该为0,总容量为0,能背的最大的重量也为0 

遍历顺序应该先遍历物品 再遍历体积。

//sum
#define MAX(a, b) (((a) > (b)) ? (a) : (b))int getSum(int* nums, int numsSize)
{int sum = 0;for(int i = 0; i < numsSize; i++){sum += nums[i]; }return sum;
}bool canPartition(int* nums, int numsSize) {int sum = 0;sum = getSum(nums, numsSize);if(sum % 2){return false;}//初始化dpint target = sum/2;int* dp = (int*)calloc((target + 1), sizeof(int));for(int i = 0 ; i < numsSize; i++){for(int j = target; j >= nums[i]; j--){dp[j] = MAX(dp[j], dp[j - nums[i]] + nums[i]);}}return dp[target] == target;}

另外,二维数组的写法如下:

//sum
#define MAX(a, b) (((a) > (b)) ? (a) : (b))int getSum(int* nums, int numsSize)
{int sum = 0;for(int i = 0; i < numsSize; i++){sum += nums[i]; }return sum;
}bool canPartition(int* nums, int numsSize) {int sum = 0;sum = getSum(nums, numsSize);if(sum % 2){return false;}//初始化dpint target = sum/2;int** dp = (int**)malloc(sizeof(int*) * (numsSize+1));for(int i = 0; i <= numsSize; i++){dp[i] = (int*)calloc(target + 1, sizeof(int));}for(int j = nums[0]; j <= target; ++j) {dp[0][j] = nums[0];}for(int i = 1; i < numsSize; i++){for(int j = 1; j <= target; j++){//状态转移公式// 若当前背包重量j小于nums[i],则其值等于只考虑0到i-1物品时的值if(j < nums[i])dp[i][j] = dp[i - 1][j];// 否则,背包重量等于在背包中放入num[i]/不放入nums[i]的较大值elsedp[i][j] = MAX(dp[i - 1][j], dp[i - 1][j  - nums[i]] + nums[i]);}}if(target == dp[numsSize - 1][target]){return true;}return false;
}

三、1049 最后一块石头重量II

 一开始阅读题目,根本联系不到01背包,但是仔细分析,题目可以转化为求2堆相近的石头,这样大堆减小堆石头,得到的值应该就是最小值。但是怎么求其中某一堆石头呢?

结合分割等和子集,找到一个target,利用01背包,就可以找到最大的dp,即找到最大的石头堆。怎么获取target,一个整体分成两部分,那么和对半分,就是需要石头堆的最大值。

int getSum(int* stones, int stonesSize)
{int sum  = 0;for(int i = 0; i < stonesSize; i++){ sum += stones[i];}return sum;
}
#define MAX(a, b)  (a) > (b)? (a) : (b)
int lastStoneWeightII(int* stones, int stonesSize) {//把问题拆分成:划分成两块相近的石头堆,就可以使用0、1背包int dp[15001] = {0};//根据题目限制int max_stone = getSum(stones, stonesSize);int target = (getSum(stones, stonesSize))/2;//目标就是找到sum的一半下dp最大值。for(int i = 0; i < stonesSize; i++){for(int j = target; j >= stones[i]; j--){dp[j] = MAX(dp[j], dp[j - stones[i]] + stones[i]);}}return max_stone - dp[target] * 2;
}

四、494 目标和

题目主要点还是如何转化:本题要如何使表达式结果为target,既然为target,那么就一定有 left组合 - right组合 = target。left + right = sum,而sum是固定的。right = sum - left。

left - (sum - left) = target

推导出 left = (target + sum)/2 。

target是固定的,sum是固定的,left就可以求出来。

此时问题就是在集合nums中找出和为left的组合。

left可以理解为正数之和, right就是负数之和,因为题目描述 + -两个运算符,只可能这两个情况。

题目转化成01背包问题。

还需要注意点,就是前面的背包问题是求最大值。但是这里求的是多少种可能组合。所以dp含义是有区别的。

int findTargetSumWays(int* nums, int numsSize, int target) {//题目是说找多少种方案if(numsSize <= 0){return 0;}int sum  = 0;for(int i = 0; i < numsSize; i++){sum += nums[i];}if(abs(target) > sum){return 0;}if((sum + target) % 2){return 0;}//初始化dpint bagsize = (sum + target)/2;//正数int* dp = (int*)calloc(bagsize + 1, sizeof(int));dp[0] = 1;for(int i = 0; i < numsSize; i++){for(int j = bagsize; j >= nums[i]; j--){dp[j] += dp[j - nums[i]];}}return dp[bagsize];
}

五、474 一和零

这里关注点是0和1是两个维度(m 和 n相当于是一个背包,两个维度的背包)。dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。递推公式为:

dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);

#define MAX(a, b)  (a) > (b)? (a) : (b)
int findMaxForm(char** strs, int strsSize, int m, int n) {int** dp = (int**)malloc(sizeof(int*) * (m + 1));for(int i = 0; i <= m; i++){dp[i] = calloc(n + 1, sizeof(int));}//初始化成0for(int i = 0; i < strsSize; i++){int zeroNum = 0;int oneNum = 0;for(int j = 0; j < strlen(strs[i]); j++){if(strs[i][j] == '0'){zeroNum++;}else{oneNum++;}}for(int p = m; p >= zeroNum; p--){for(int q = n; q >= oneNum; q--){dp[p][q] = MAX(dp[p][q], dp[p - zeroNum][q - oneNum] + 1);}}}return dp[m][n];
}

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

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

相关文章

【C语言】/*printf 函数*/

目录 printf 函数 1.1 语法形式 1.2 基本使用 1.3 占位符 1.4 占位符的输出格式 1.4.1 限定宽度 1.4.2 总是显⽰正负号 1.4.3 限定⼩数位数 1.4.4 输出部分字符串 printf 函数 1.1 语法形式 语法形式&#xff1a;int printf(const char* format, ...); 功能&#xff…

记某APP登录逆向解密过程

最近在学习APP逆向相关的知识&#xff0c;刚好拿到了一个APP目标&#xff0c;该APP登录过程存在加密&#xff0c;所以记录下逆向破解的过程。流程 先介绍下拿到该APP后续所做的一些工作流程 选择相应版本安装到测试机当中进行抓包&#xff0c;查看数据包分析登录请求包&#x…

中国目前比较有影响力的人物颜廷利:不能升命, 活着何用?

不能‘升命’&#xff0c; 活着何用&#xff1f;…&#xff08;升命学说&#xff09; 21世纪东方哲学家思想家、科学家、当代中国教育界知名教授、专业周易起名改名字、易经姓名学专家、目前比较有影响力的人物、现代国学大师泰斗杰出代表颜廷利教授在《升命学说》‘净化论’里…

PCL 点云中的平面点云提取

平面点云提取 一. 索引提取1.1 算法概念1.2 算法流程1.3 主要函数二.代码示例三.结果示例一. 索引提取 1.1 算法概念 平面点云提取:是指从点云数据中提取出属于平面的点的过程。 1.2 算法流程 使用pcl::SACSegmentation类进行点云分割的基本步骤如下: 创建一个pcl::SACSegm…

Java 类与对象

目录 1 类是什么 1.1 面向对象 1.2 面向对象与面向过程 2 类定义和使用 2.1 类的定义格式 2.2 练习定义一个狗类 3 类的实例化 4 this引用 5 对象的构造与初始化 5.1 构造方法与初始化 5.2 默认初始化 5.3 就地初始化 1 类是什么 关于类是什么&#xff0c;我们需要对…

开源版本管理系统的搭建一:SVN服务端安装

作者&#xff1a;私语茶馆 1.Windows搭建SVN版本管理系统 点评&#xff1a;SVN本身非常简洁易用&#xff0c;VisualSVN文档支撑非常好&#xff0c;客户端TortoiseSVN非常专业。5星好评。 1.1.SVN概要和组成 背景介绍 Svn是一个开源版本管理系统&#xff0c;由CollabNet公司…

一、Mysql索引的底层数据结构与算法

Mysql索引的底层数据结构与算法 前言一、索引数据结构为什么 MySQL 的索引要使用 B 树而不是其他树形结构?比如 B 树?为什么InnoDB存储引擎选择使用Btree索引结构&#xff1f; 二、索引分类思考&#xff1a;以下SQL语句&#xff0c;那个执行效率高&#xff1f;为什么&#xf…

SQL如何利用Bitmap思想优化array_contains()函数

目录 0 问题描述 1 位图思想 2 案例实战 3 小结 0 问题描述 在工作中&#xff0c;我们往往使用array_contains()函数来进行存在性问题分析&#xff0c;如判断某个数是否在某个数组中&#xff0c;但是当表数据量过多&#xff0c;存在大量array_contains()函数时&#xff0c;…

【软件测试】测试用例设计方法

1. 等价类划分法1.1. 等价类划分法的定义1.2. 有效等价类和无效等价类1.3. 等价类划分法实例分析 2. 边界值分析法2.1. 边界值分析法的定义2.2. 边界点2.3. 边界值法实例分析 3. 判定表法3.1. 如何用判定表法设计测试用例3.2. 判定表法实例分析 4. 正交表法4.1. 什么是正交表4.…

Spring扩展点(二)Spring事务生命周期

Spring事务生命周期 Spring事务事务生命周期 接口 TransactionSynchronizationTransactionalEventListener&#xff08;另一种监听事务周期的方式&#xff09; Spring事务 Spring对JDBC事务做了封装&#xff0c;使其易于使用。主要分为声明式事务和编程式事务。 Transactiona…

批量美化图片,轻松实现多张图片描边,让图片瞬间焕发新生!

图片已成为我们日常生活中不可或缺的一部分。无论是社交媒体上的个人分享&#xff0c;还是商业宣传中的产品展示&#xff0c;高质量、精美的图片都扮演着至关重要的角色。然而&#xff0c;对于许多人来说&#xff0c;图片处理仍然是一个令人头疼的问题。现在&#xff0c;我们为…

商超物联网方案-Hotspot Service和客流分析方案概述

商超物联网方案-Hotspot Service和客流分析方案概述 场景概述 大型商场、大型综合体在相互竞争及线上消费的影响下&#xff0c;利润增长缓慢&#xff0c;迫切需要通过提供个性化服务提升顾客购物体验&#xff0c;促进利润增长。 向不同顾客推送其感兴趣的广告&#xff0c;不仅…

NodeJS中实现一个真正的Sleep,Sleep期间不影响其它线程执行

NodeJS中实现一个真正的Sleep&#xff0c;Sleep期间不影响其它线程执行 Node.js 是基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;它采用了单线程、事件驱动和非阻塞I/O模型。由于JavaScript是单线程的&#xff0c;传统意义上的线程睡眠&#xff08;如Java中的Thread.…

c++游戏小技巧16:实例1(地牢生成算法)

1.前言 (头图) &#xff08;其实最开始是想写恶魔轮盘的&#xff0c;但没想到它竟然更新了&#xff09; &#xff08;等我有时间在更&#xff0c;最近很忙&#xff0c;玩第五玩的&#xff09; 想法来源&#xff1a;房间和迷宫&#xff1a;一个地牢生成算法https://indienova…

机器学习(五)之损失函数

上面几节讲了监督学习和非监督学习的一些算法&#xff08;目前还不完整&#xff0c;会慢慢补充哒) 如果文章内容有错误&#xff0c;欢迎小伙伴在评论区指出! 前言&#xff1a; 损失函数在机器学习中非常重要&#xff0c;直接关乎模型的好坏&#xff08;so?学好它&#xff09;…

STM32G474 CMAKE VSCODE 开发环境搭建

本篇博文尝试搭建 stm32g474 的开发环境 一. 工具安装 1. 关于 MinGW、OpenOCD、Zadig 这些工具的下载和安装见 JlinkOpenOCDSTM32 Vscode 下载和调试环境搭建_vscode openocd stm32 jlink-CSDN博客 2. 导出一个 STM32 的 CMAKE 工程&#xff0c;这里略过。 3. 安装 ninja …

matlab期末知识

1.期末考什么&#xff1f; 1.1 matlab操作界面 &#xff08;1&#xff09;matlab主界面 &#xff08;2&#xff09;命令行窗口 &#xff08;3&#xff09;当前文件夹窗口 &#xff08;4&#xff09;工作区窗口 &#xff08;5&#xff09;命令历史记录窗口 1.2 matlab搜索…

用C#写一个特性,在函数上面可以自动计算函数耗时情况

用C#写一个特性&#xff0c;在函数上面可以自动计算函数耗时情况 TimingAttribute类是自定义的特性类&#xff0c;用来标记需要计时的方法。TimingInterceptor类是一个拦截器&#xff0c;它通过反射来拦截被TimingAttribute标记的方法&#xff0c;并在方法执行前后进行计时。My…

Elasticsearch:对 Java 对象的 ES|QL 查询

作者&#xff1a;Laura Trotta ES|QL 是 Elasticsearch 引入的一种新的查询语言&#xff0c;它将简化的语法与管道操作符结合起来&#xff0c;使用户能够直观地推断和操作数据。官方 Java 客户端的新版本 8.13.0 引入了对 ES|QL 查询的支持&#xff0c;提供了一个新的 API&…

Redis 实战2

系列文章目录 本文将从字典的实现、哈希算法、解决键冲突、rehash、渐进式rehash几方面来阐述 Redis 实战Ⅱ 系列文章目录字典的实现哈希算法解决键冲突rehash渐进式 rehash渐进式 rehash 执行期间的哈希表操作 字典 API总结 字典的实现 Redis 的字典使用哈希表作为底层实现&…