「动态规划」简单多状态dp问题

这篇具有很好参考价值的文章主要介绍了「动态规划」简单多状态dp问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

以经典问题“打家劫舍”来解释简单多状态dp问题和解决方法

打家劫舍I

题目链接:打家劫舍I
「动态规划」简单多状态dp问题,算法详解,动态规划,算法

这种问题就是在某一个位置有多个状态可以选择,选择不同的状态会影响最终结果
在这道题中就是小偷在每一个房屋,可以选择偷或不偷,每一次选择都会影响最终偷窃金额

  1. 状态表示
    因为每一步都有两个状态,所以我们要用两张dp表来表示,分别记为 f 和 g,f[i]表示从开始到第 i 号房屋,偷窃第 i 号房屋可获得的最大金额;g[i[则表示不偷第 i 号房屋可获得的最大金额
  2. 状态转移方程
    推导转移方程常用的策略就是找最近的一步,f[i]最近的一步就是 i - 1,而偷了第 i 号房屋就意味着第 i - 1 号不能偷,也就是 g[i-1] + nums[i]
    而对于g[i],因为在此状态下第 i - 1 号房间可偷可不偷,也就是对应f[i-1]g[i-1],我们要的是最大金额,所以取它们两者中的较大值即可,即g[i] = Math.max(f[i - 1],g[i - 1])
  3. 初始化
    状态转移方程涉及了 i - 1,所以我们要初始化 f[0]g[0],显然f[0]初始化为nums[0]就ok了,g[0]初始化为0
  4. 填表顺序
    从左往右填
  5. 返回值
    比较 f 和 g 最后一个元素,谁大就返回谁

代码如下:

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        int[] f = new int[n];
        int[] g = new int[n];
        f[0] = nums[0]; g[0] = 0;
        for(int i = 1;i < n;i++) {
            f[i] = g[i-1] + nums[i];
            g[i] = Math.max(f[i-1],g[i-1]);
        }
        return Math.max(f[n-1],g[n-1]);
    }
}

当然,我们要讲的肯定不止一道题,上面的题只是基础题。而当我们面对中等题、难题时,要有能力将它们转化为我们见过的题,下面以两道题示例:

打家劫舍II

题目链接:打家劫舍II
「动态规划」简单多状态dp问题,算法详解,动态规划,算法
在这道题中,房屋的排列变成了环形
如果偷第1个房屋,那就不能偷第二个和最后一个,此时第三个房屋到最后一个房屋其实是直线形,那就可以用打家劫舍I的思路来解决
如果不偷第一个房屋,那么第二个房屋到最后一个房屋也是直线形,也可以参考上面的思路
通过讨论不同的情况,我们都可以把环形的问题转化为之前解决过的直线形的问题

那接下来只需对两种情况分别使用打家劫舍I的思路,然后返回最大值即可,因为代码会涉及到相同的的部分,所以我们封装为一个函数

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        return Math.max(rob1(nums,2,n-2)+nums[0],rob1(nums,1,n-1));
    }

    public int rob1(int[] nums,int left,int right) {  //对[left,right]区间进行“打家劫舍”
        if(left > right) return 0;
        int n = nums.length;
        int[] f = new int[n];
        int[] g = new int[n];
        f[left] = nums[left];
        for(int i = left+1;i <= right;i++) {
            f[i] = g[i-1] + nums[i];
            g[i] = Math.max(f[i-1],g[i-1]);
        }
        return Math.max(f[right],g[right]);
    }
}

删除并获得点数

「动态规划」简单多状态dp问题,算法详解,动态规划,算法
这道题意思就是说选了一个点数之后,不能再选大小和它相邻的点数,因为数组中可能会有多个相同的点数,所以我们先把相同的点数求和,放进一个新的数组(新数组和每个点数之间存在映射关系,比如点数1就放在该数组下标为1的位置),然后我们可以对新数组采用打家劫舍文章来源地址https://www.toymoban.com/news/detail-840415.html

class Solution {
    public int deleteAndEarn(int[] nums) {
        int n = nums.length;
        int max = 0;
        int[] sum = new int[10001];  //记录nums中每个数字出现的总和
        for(int i = 0;i < n;i++)
            sum[nums[i]] += nums[i];

        //对sum进行打家劫舍
        return rob(sum);
    }

    public int rob(int[] sum) {
        int n = sum.length;
        int[] f = new int[n];
        int[] g = new int[n];
        f[1] = sum[1];
        for(int i = 2;i < n;i++) {
            f[i] = g[i-1] + sum[i];
            g[i] = Math.max(g[i-1],f[i-1]);
        }
        return Math.max(f[n-1],g[n-1]);
    }
}

到了这里,关于「动态规划」简单多状态dp问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【动态规划】简单多状态dp问题(1)打家劫舍问题

    打家劫舍问题 传送门:面试题 17.16. 按摩师 题目: 1.1 题目解析 越难的dp问题,看示例只能起到了解题目的效果,一般推不出啥普遍的规律,所以接下来就是我们的算法原理,通过动归的思想去理解,才会豁然开朗! 1.2 算法原理 1.2.1 状态表示 我们需要通过经验 + 题目要求去

    2024年02月12日
    浏览(40)
  • 【动态规划】12简单多状态dp问题_打家劫舍II_C++ (medium)

    题目链接:leetcode打家劫舍II 目录 题目解析: 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目让我们求 在不触动警报装置的情况下  ,能够偷窃到的最高金额。 由题可得: 第一个房屋和最后一个房屋是紧挨着的 如果两间相邻的房屋在同一晚

    2024年02月02日
    浏览(46)
  • 【动态规划专栏】专题三:简单多状态dp--------3.删除并获得点数

    本专栏内容为:算法学习专栏,分为优选算法专栏,贪心算法专栏,动态规划专栏以及递归,搜索与回溯算法专栏四部分。 通过本专栏的深入学习,你可以了解并掌握算法。 💓博主csdn个人主页:小小unicorn ⏩专栏分类:动态规划专栏 🚚代码仓库:小小unicorn的代码仓库🚚

    2024年03月22日
    浏览(42)
  • acwing算法基础之动态规划--数位统计DP、状态压缩DP、树形DP和记忆化搜索

    暂无。。。 暂无。。。 题目1 :求a~b中数字0、数字1、…、数字9出现的次数。 思路:先计算1~a中每位数字出现的次数,然后计算1~b-1中每位数字出现的次数,两个相减即是最终答案。 那么,如何计算1~a中每位数字出现的次数呢? 首先,将a的每一位存入向量num中,例如a=123

    2024年02月04日
    浏览(49)
  • AcWing算法学习笔记:动态规划(背包 + 线性dp + 区间dp + 计数dp + 状态压缩dp + 树形dp + 记忆化搜索)

    算法 复杂度 时间复杂度0(nm) 空间复杂度0(nv) 代码 算法 通过滚动数组对01背包朴素版进行空间上的优化 f[i] 与 f[i - 1]轮流交替 若体积从小到大进行遍历,当更新f[i, j]时,f[i - 1, j - vi] 已经在更新f[i, j - vi]时被更新了 因此体积需要从大到小进行遍历,当更新f[i, j]时,f[i - 1,

    2024年02月21日
    浏览(42)
  • ★动态规划(DP算法)详解

    什么是动态规划:动态规划_百度百科 内容太多了不作介绍,重点部分是无后效性,重叠子问题,最优子结构。 问S-P1和S-P2有多少种路径数,毫无疑问可以先从S开始深搜两次,S-P1和S-P2找出所有路径数,但是当这个图足够大,那就会超时。 动态规划旨在用 空间换时间 ,我们

    2024年02月04日
    浏览(47)
  • c++ 算法之动态规划—— dp 详解

    dp 是 c++ 之中一个简单而重要的算法,每一个 OIer 必备的基础算法,你知道它究竟是什么吗? 目录 一、简介         1.为什么不能贪心?         2.揭秘 dp   二、应用         1.定义         2.边界值         3.动态转移方程         4.结果         5.代码

    2024年04月09日
    浏览(45)
  • 【算法】动态规划(dp问题),持续更新

    介绍本篇之前,我想先用人话叙述一般解决动态规划问题的思路: 动态规划的问题,本身有许多产生结果的可能,需要在具体题目下得到满足某个条件的解。 如何得到呢? 我们就需要根据这个具体问题,建立一个状态表( dp 表 ),在这张 dp 表中的每一个位置的数据都有明

    2024年02月04日
    浏览(48)
  • 【算法学习】简单多状态-动态规划

            本篇博客记录动态规划中的简单多状态问题。         在之前的动态规划类型的题中,我们每次分析的都只是一种或者某一类的状态,定义的dp表也是围绕着一种状态来的。         现在可能对于一种状态,存在几种不同的子状态,在状态转移过程中相互影响。此时

    2024年01月18日
    浏览(39)
  • C++ DP算法,动态规划——背包问题(背包九讲)

    有N件物品和一个容量为 V V V 的背包。放入第i件物品耗费的空间是 C i C_i C i ​ ,得到的价值是 W i W_i W i ​ 。 求解将哪些物品装入背包可使价值总和最大。 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。 用子问题定义状态:即 F [ i , v ] F[i, v] F

    2024年02月16日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包