打家劫舍Ⅰ(LeetCode-198)

1. 问题描述:

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

2. 示例:

(1)

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4。

(2)

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。偷窃到的最高金额 = 2 + 9 + 1 = 12 。

3. 题解:

此题要求我们求得一夜之内能够偷窃到的最高金额,这是一个求最优解的问题,而且满足DP三大特性(不清楚的小伙伴可以参考之前的文章:https://blog.csdn.net/m0_51339444/article/details/123716692),因此显然这是一个DP问题。下面我们来看一下规划方程的求解过程:

dp[i]表示以偷i号住户为结尾的最优盗窃方案(i是一定要偷的),可能对这里有些疑惑,那我解释一下:任何一种偷法肯定不可能一家都不偷,既然偷了,那最优解肯定以偷某家为最后一家,我们只需要依次求出以偷i为结尾的最优盗窃方案,最后对dp数组取max即可。
如上图所示:偷i了,就不可能偷i-1,上一个最优子问题有可能是以偷i-2为结尾的,也可能是i-3,但是思考一下能不能是偷i-4呢? Impossible! 因为如果上一个子问题是以i-4结尾,那研究的是dp[i],那就会违背最优化原则,因为你偷了i-4,为什么不偷i-2和i,而只偷i ? 显然不合理。因此我们只需要考虑dp[i-2]和dp[i-3],规划方程如下:
`
dp[i] = max(dp[i - 2] + nums[i], dp[i - 3] + nums[i])

然后我们解决一下DP边界问题,很容易理解:
dp[0] = nums[0]; dp[1] = nums[1]; dp[2] = nums[0] +nums[2];

4. 代码:

class Solution {
public:int rob(vector<int>& nums) {int len = size(nums);int dp[len];if(len>=1)dp[0] = nums[0];if(len>=2)dp[1] = nums[1];if(len>=3)dp[2] = nums[0] + nums[2];for(int i = 3; i < len; ++i){dp[i] = max(dp[i - 2] + nums[i], dp[i - 3] + nums[i]);}sort(dp, dp + len);return dp[len-1];}
};

打家劫舍Ⅱ(LeetCode-213)

1. 问题描述:

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

2. 示例:

(1)

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

(2)

输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4 。

(3)

输入:nums = [1,2,3]
输出:3

3. 题解:


我们刚才做了打家劫舍1,不能白做,是吧~~ 那就要想办法把打家劫舍2变成1。看下上图的分界线,如果偷0的话,那就不能偷n-1,就可以讲问题转化为求0 to n-2的最优解问题。如果不偷0,那问题就转化为1 to n-1的最优解问题。之后不做赘述,还没理解的uu可以康康代码。 代码不简洁因为想增强可读性。

4. 代码:

class Solution {
public:int rob(vector<int>& nums) {int len = nums.size();// 不偷第一家房子int dp1[len];memset(dp1, 0, len*sizeof(int));// if(len >= 1)//     dp1[0] = 0;if(len >= 2)dp1[1] = nums[1];if(len >= 3)dp1[2] = nums[2];if(len > 3)dp1[3] = nums[1] + nums[3];if(len > 4){for(int i = 4; i < len; ++i){dp1[i] = max(dp1[i-2] + nums[i], dp1[i - 3] + nums[i]);}}sort(dp1, dp1 + len);int max1 = dp1[len - 1];// 偷第一家int dp2[len];memset(dp2, 0, len*sizeof(int));if(len >= 1) dp2[0] = nums[0];if(len >= 2)dp2[1] = -100;if(len == 3)dp2[2] = -100;if(len > 3)dp2[2] = nums[0] + nums[2];if(len > 4){for(int i = 3; i < len - 1; ++i){dp2[i] = max(dp2[i-2] + nums[i], dp2[i - 3] + nums[i]);}}sort(dp2, dp2 + len);int max2 = dp2[len - 1];int MAX = max(max1, max2);return MAX;}
};

打家劫舍Ⅲ(删除并获得点数)(LeetCode-740)

1. 问题描述:

给你一个整数数组 nums ,你可以对它进行一些操作。每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

2. 示例:

(1)

输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。

(2)

输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。

3. 题解:

这道题看似和前两题毫无关系,但是我们还是可以想办法转化成类似的问题。首先,这道题有个隐藏点:当我们选择了nums[i]这个数,那么我们就相当于获得了nums中所有等于nums[i]的点数,因为我们可以重复这个操作,但是代价是放弃nums中所有等于nums[i]-1和nums[i]+1的点数(类似前两题中的不能偷相邻两个住户)。
我们可以构建一个cnt数组,索引即数值,对应元素大小为该数值的个数。
规划方程为:
dp[i] = max(dp[i - 1], dp[i - 2] + cnt[i] * i)
边界条件为: dp[0] = 0; dp[1] = 1*cnt[1];

4. 代码:

class Solution {
public:int deleteAndEarn(vector<int>& nums) {int len = nums.size();if(len < 1)return 0;int maxn = 0;for(int i = 0; i < len; ++i){maxn = max(maxn, nums[i]);}int cnt[maxn + 1];memset(cnt, 0, (maxn + 1)*sizeof(int));int dp[maxn + 1];memset(dp, 0, (maxn + 1)*sizeof(int));for(int i = 0; i < len; ++i){int k = nums[i];cnt[k]++;}dp[0] = 0;dp[1] = 1*cnt[1];for(int i = 2; i <= maxn; ++i){dp[i] = max(dp[i - 1], dp[i - 2] + cnt[i] * i);}return dp[maxn];}
};

DP算法——打家劫舍系列相关推荐

  1. 打家劫舍系列(dp)

    引言 打家劫舍类的题目是动态规划里的经典题目,有很多种变换形式,下面就介绍一下力扣里面的所有打家劫舍的题目: 打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯 ...

  2. dp笔记:关于DP算法和滚动数组优化的思考

    从网上总结了一些dp的套路以及对滚动数组的一些思考,现记录如下,希望以后回顾此类算法时会有所帮助. 目录 1.DP算法经验 1.DP算法核心: 2.DP算法类别以及例题 例1:三步问题 例2:最小路径 ...

  3. 经典算法研究系列:二、Dijkstra 算法初探

    经典算法研究系列:二.Dijkstra 算法初探  July   二零一一年一月 ====================== 本文主要参考:算法导论 第二版.维基百科. 写的不好之处,还望见谅. 本 ...

  4. if嵌套while循环语句_选考VB算法专题系列讲座13嵌套If和多分支语句

    视频内容: 本视频是给学生复习If语句时的授课内容,长长的寒假过后,很多学生连最基本的东西的忘记了,只好从最简单的开始复习.本视频讲解了使用嵌套If和多分支语句解决的两个问题,讲解非常详细,基础不够扎 ...

  5. boost::geometry模块多边形DP算法简化示例

    boost::geometry模块多边形DP算法简化示例 实现功能 C++实现代码 实现功能 boost::geometry模块多边形DP算法简化示例 C++实现代码 #include <boo ...

  6. 遗传算法经典实例代码_经典算法研究系列 之 深入浅出遗传算法

    关注数学,关注AI,关注我们公众号ID:Math-AI 经典算法研究系列 遗传算法 1 初探遗传算法 Ok,先看维基百科对遗传算法所给的解释: 遗传算法是计算数学中用于解决最优化的搜索算法,是进化算法 ...

  7. 经典算法研究系列:十、从头到尾彻底理解傅里叶变换算法、下

    经典算法研究系列:十.从头到尾彻底理解傅里叶变换算法.下 作者:July.dznlong   二零一一年二月二十二日 推荐阅读:The Scientist and Engineer's Guide t ...

  8. 经典算法研究系列:十、从头到尾彻底理解傅里叶变换算法、上

     经典算法研究系列:十.从头到尾彻底理解傅里叶变换算法.上 作者:July.dznlong   二零一一年二月二十日 推荐阅读:The Scientist and Engineer's Guide t ...

  9. 经典算法研究系列:七、深入浅出遗传算法,透析GA本质【转载】

    本文由July 发表在他的博客中,原文参见http://blog.csdn.net/v_JULY_v/archive/2011/01/12/6132775.aspx,对遗传算法分析的很透彻,是学习算法 ...

  10. Leetcode 64. 最小路径和 -- DP算法

    Time: 20190831 题目描述 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: ...

最新文章

  1. RSync实现文件备份同步
  2. 阿里AI再摘一冠,大幅提高视觉对话世界纪录
  3. 考前自学系列·计算机组成原理·中央处理器知识点
  4. C/C++中程序内存区域划分大总结
  5. consul 1.2 支持service mesh
  6. 趣学python3(8)-循环语句(2)
  7. Git之深入解析48个经典操作场景的分析和处理,专治不会合并代码
  8. 顺序表链表 LeetCode专项练习 [19]\[24]
  9. 联合使用 HTML 5、地理定位 API
  10. transformers PreTrainedTokenizer
  11. Source does not fit in dest
  12. 解决word2016复制粘贴后一直未响应
  13. iPhone 手势识别
  14. oracle静态注册6,oracle数据库静态注册
  15. 屏蔽鼠标右键,F1帮助和常用快捷键
  16. 软考信息安全工程师+2021-01-30 1.网络信息安全概述+重点
  17. Win7 64位静态过PG,文件修改记录,备忘
  18. 阿里云免费教你使用营销引擎
  19. java.lang.UnsupportedOperationException: Currently Flink doesn‘t support individual window table-val
  20. 学习笔记:简谈BUCK电路

热门文章

  1. Landlock:一种新型Linux安全模块
  2. 5.6 深度卷积神经网络(AlexNet)
  3. 【汇智学堂】-JS菜鸟版手机小游戏(五子棋游戏之一---准确落下棋子)
  4. suse 11添加阿里源
  5. 课堂笔记_图形学基础课程_简单认知00
  6. 银联支付接口+支付宝接口统一支付功能
  7. 卡尔曼滤波算法 C语言实现
  8. 十种经典运放电路分析
  9. 行为树(Behavior Tree)详细介绍
  10. 根据出库、入库表,实现对库存的信息查询