当前位置: 首页 > news >正文

算法第31天|动态规划:最后一块石头的重量Ⅱ、目标和、一和零

 今日总结:

        1、最后一块石头的重量:

                需要明确:dp[j]表示的是在容量为j的条件下,所能达到的最大的价值,这个题目中,价值就是石头重量重量(所占容量)也是石头重量

                所以就是在计算:在重量容量为sum/2时,能不能达到最大的重量,所以dp[sum/2]<=sum/2,又因为sum/2是向下取整,所以另一半一定>=sum/2

                所以最终结果: return (sum -dp[sum/2])-dp[sum/2];

        2、目标和

                需要思考如何得出的01背包问题,dp数组、下标、重量、价值、递推公式等

        3、一和零

                需要思考如何得出的01背包问题,dp数组、下标、重量、价值、递推公式等

最后一块石头的重量Ⅱ

题目链接:1049. 最后一块石头的重量 II - 力扣(LeetCode)

代码随想录

整体思路:

        跟前一个题进行对比(分割等和子集)

        1、分割等和子集,最终的目的是分成两个子集,使子集的和相同,也就是说:每个子集的和都必须是sum/2才能满足要求。

                背包问题:一个背包有最大容量,如何装若干物品,去获得最大的价值

                背包容量:达到sum/2就是最大的容量

                物品:集合中的元素

                物品价值:元素本身的值

                物品重量:元素本身的值 

        dp[j]:表示在容量为j条件下,所能达到的最大价值(最大的和 dp[j]<=j,因为j就是sum/2,dp[j]就是在sum/2下,能达到的最大的和)

        如果在dp[sum/2]<sum/2,就说明分割失败

        2、最后一块石头的重量,任意两块石头作比较,相同就粉碎,不同就剩下大的减去小的重量-->可以将石头数组分成两份,尽量相同,然后大的份-小的份就是最后一块的质量

        相当于分割等和子集,但是会出现最后两个不相同的情况,需要额外判断

        背包容量:寻找的是sum/2

        物品:石头元素

        物品价值:价值就是在比较重量问题-->重量

        物品重量:就是石头重量

        dp[j]:表示的是在容量为j条件下,所能达到的最大的重量(dp[j]<=j)

整体代码:

class Solution {
public:int lastStoneWeightII(vector<int>& stones) {int sum =0;for(int i=0;i<stones.size();i++){sum +=stones[i];}int target = sum/2;//获取最大容量vector<int>dp(30000,0);for(int i=0;i<stones.size();i++){for(int j=target;j>=stones[i];j--)//只要当前的容量大于所遍历的这一次的重量,就可以容纳dp[j-stones[i]]+value,就可以判断是不是dp[j]变大了{dp[j] = max(dp[j],dp[j-stones[i]]+stones[i]);}}//因为sum可能是奇数,所以sum/2就肯定小于一般是向下取整//所以最终返回的石头重量:return sum -dp[target] - dp[target];}
};

目标和

题目链接:494. 目标和 - 力扣(LeetCode)

代码随想录

整体思路:

 //将加法加起来left,减法加起来(绝对值 )right
        left  -  right  = target
        left  +  right  = sum
        left - (sum -left)  =target
        left = ( target +sum )/2
        所以问题可以转化为在nums中寻找有多少方法和为left,每个数只能选择取或者不取-->01背包问题
        1、确定dp[j]及下标的含义:
            dp[j]的含义是在容量(nums[i])为j的条件下,能够达到目标容量j的最多的方法(注意审题:求得是方法) 
            容量j :left
            物品价值nums[i] 就是整数值
            物品重量nums[i] 也是整数值
        2、确定dp数组的递归公式(状态转移方程)
            可将整体分为:取当前物品i+不取当前物品i
            取物品i一定要求的是当前容量j>物品i的重量
            同时,因为是一维滚动数组,所以必须遍历重量从后往前,也就是说当前的dp[j] = 之前的dp[j]+之前的dp[j-nums[i]]

整体代码:

class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {//将加法加起来left,减法加起来(绝对值 )right//left  -  right  = target//left  +  right  = sum//left - (sum -left)  =target//left = ( target +sum )/2//所以问题可以转化为在nums中寻找有多少方法和为left,每个数只能选择取或者不取-->01背包问题//1、确定dp[j]及下标的含义://dp[j]的含义是在容量(nums[i])为j的条件下,能够达到目标容量j的最多的方法(注意审题:求得是方法) //容量j :left//物品价值nums[i] 就是整数值//物品重量nums[i] 也是整数值//2、确定dp数组的递归公式(状态转移方程)//可将整体分为:取当前物品i+不取当前物品i//取物品i一定要求的是当前容量j>物品i的重量//同时,因为是一维滚动数组,所以必须遍历重量从后往前,也就是说当前的dp[j] = 之前的dp[j]+之前的dp[j-nums[i]]int sum =0;for(int i=0;i<nums.size();i++) sum +=nums[i];if((target+sum)%2==1)return 0;if(abs(target)>sum) return 0;int left = (target+sum)/2;vector<int> dp(left+1,0);//最大容量设置//初始化,与二维数组不同,只需要设置dp[0]dp[0] =1;for(int i=0;i<nums.size();i++){for(int j=left;j>=nums[i];j--)//只需要看大于当前物品的部分,从后往前:当前的dp[j]用的是之前的数据,而不是这次修改的数据{dp[j] = dp[j] + dp[j-nums[i]];}}return dp[left];}
};

一和零

题目链接:474. 一和零 - 力扣(LeetCode)

代码随想录

整体思路:

        对于整体来说,是从二进制字符串数组strs中选取若干个str,使得子集中拥有最多m个0和n个1
        对于每一个str必须是选或者不选-->01背包问题
        物品:每个字符串
        物品重量:占据的0、占据的1,两个维度的重量
        物品价值:1,每个物品都是一个小的子集
        1、确定dp[i][j]及下标:
            dp[][]表示在0容量为i,1容量为j的条件下,最大的子集
            i表示0的容量
            j表示1的容量
        2、确定dp的递推公式(状态转移方程)
            分为取当前的str、不取当前的str
            取当前的str,必须要求i>str中的0的数量,j>str中的1的数量 dp[i][j] =  dp[i-zeronum][j-onenum] +1
            不取当前的str dp[i][j] = dp[i][j];

整体代码:

class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {//对于整体来说,是从二进制字符串数组strs中选取若干个str,使得子集中拥有最多m个0和n个1//对于每一个str必须是选或者不选-->01背包问题//物品:每个字符串//物品重量:占据的0、占据的1,两个维度的重量//物品价值:1,每个物品都是一个小的子集//1、确定dp[i][j]及下标://dp[][]表示在0容量为i,1容量为j的条件下,最大的子集//i表示0的容量//j表示1的容量//2、确定dp的递推公式(状态转移方程)//分为取当前的str、不取当前的str//取当前的str,必须要求i>str中的0的数量,j>str中的1的数量 dp[i][j] =  dp[i-zeronum][j-onenum] +1//不取当前的str dp[i][j] = dp[i][j];vector<vector<int>>dp(m+1,vector<int>(n+1,0));for(auto str  :  strs){int zeronum =0,onenum=0;for(auto c :str){if(c=='0')zeronum++;else onenum++;}for(int i=m;i>=zeronum;i--){for(int j=n;j>=onenum;j--){dp[i][j] = max(dp[i-zeronum][j-onenum] +1,dp[i][j]);}}}return dp[m][n];}
};
http://www.dtcms.com/a/316414.html

相关文章:

  • 二分查找
  • 算法训练营day41 动态规划⑧ 121. 122.123.买卖股票的最佳时机1.2.3
  • 常用技术资料链接
  • Spring小细节
  • oelove奥壹新版v11.7旗舰版婚恋系统微信原生小程序源码上架容易遇到的几个坑,避免遗漏参数白屏显示等问题
  • Electron-updater + Electron-builder + IIS + NSIS + Blockmap 完整增量更新方案
  • 物联网后端系统架构:从基础到AI驱动的未来 - 第十章:AI促进IOT领域发生革命式发展
  • WebRTC采集模块技术详解
  • 阿里云百炼平台创建智能体-上传文档
  • Mysql使用Canal服务同步数据->ElasticSearch
  • Linux-环境变量
  • Transformer的并行计算与长序列处理瓶颈
  • 视频转二维码在教育场景中的深度应用
  • QT跨线程阻塞调用方法总结
  • SpringMVC 6+源码分析(四)DispatcherServlet实例化流程 3--(HandlerAdapter初始化)
  • 【机器学习深度学习】 知识蒸馏
  • 2.4.9-2.5.1监控项目工作-控制质量-确认范围-结束项目或阶段
  • 三极管三种基本放大电路:共射、共集、共基放大电路
  • 后量子时代已至?中国量子加密技术突破与网络安全新基建
  • 无监督学习聚类方法——K-means 聚类及应用
  • CMAQ空气质量模式实践技术及案例分析应用;CMAQ空气质量模式配置、运行
  • Go语言实战案例:使用sync.Mutex实现资源加锁
  • 一次完整的 Docker 启动失败排错之旅:从 `start-limit` 到 `network not found
  • 三坐标测量机全自研扫描测头+标配高端性能,铸就坚实技术根基
  • 如何实现一个简单的基于Spring Boot的用户权限管理系统?
  • layernorm backward CUDA优化分析
  • Spring Boot 集成 ShardingSphere 实现读写分离实践
  • MySQL数据类型介绍
  • langchain入门笔记01
  • 【nvidia-B200】Ubuntu 22.04 中安装指定版本的 NVIDIA 驱动时出现依赖冲突