简单多状态dp问题 + 总结(一)

文章目录

按摩师

题目链接

题解

  1. 细节处理:题目是有没有客人的时候,所有n等于零时返回零
  2. 状态表示:到达i位置时的最长预约时长
  3. 状态转移方程:到达i位置的时候分为选或者不选,选的话,前一个位置就是不选,不选的话,前一个位置可以是不选或者是选中的最大值

代码

cpp 复制代码
class Solution 
{
public:
    int massage(vector<int>& nums) 
    {
        int n = nums.size();
        if(n == 0) return 0;// 空数组是没有预约时间的
        vector<int> f(n);// 最后一个状态选
        vector<int> g(n);// 最后一个状态不选
        f[0] = nums[0];
        for(int i = 1;i < n;i++)
        {
            f[i] = g[i-1] + nums[i];
            g[i] = max(f[i-1],g[i-1]);
        }
        return max(g[n-1],f[n-1]);
    }
};

打家劫舍II

题目链接

题解

  1. 这题的思路和按摩师几乎一模一样,只不过可以分为第一个位置偷和第一个位置不偷的情况,最后比较两种情况哪种的金额最大
  2. 第一个位置偷的情况,那么最后一个位置和第二个位置都不能偷,在2,n-2内进行一次按摩师
    第一个位置不偷的情况,在1,n-1区间内进行一次按摩师

代码

cpp 复制代码
class Solution 
{
public:
    int rob(vector<int>& nums) 
    {
        int n = nums.size();
        if(n == 0) return 0;
        if(n == 1)
        {
            return nums[0];
        }
        if(n == 2)
        {
            return nums[0] > nums[1] ? nums[0] : nums[1];
        }

        vector<int> f(n);// 最后一个位置偷
        vector<int> g(n);// 最后一个位置不偷

        f[2] = nums[2],g[2] = 0;
        int x = 0,y = 0; 
        // 第一个位置偷
        for(int i = 3;i < n-1;i++)
        {
            f[i] = g[i-1] + nums[i];
            g[i] = max(g[i-1],f[i-1]);
        }
        x = nums[0] + max(f[n-2],g[n-2]);
        // 第一个位置不偷

        f[1] = nums[1],g[1] = 0;
        for(int i = 2;i < n;i++)
        {
            f[i] = g[i-1] + nums[i];
            g[i] = max(g[i-1],f[i-1]);
        }
        y = max(f[n-1],g[n-1]);
        return max(x,y);
    }
};

删除并获得点数

题目链接

题解

  1. 可以先将数组预处理为下标对应的数的所有和相加,这样可以转换为打家劫舍问题,排序后选了一个数,相邻的两个数不能选
  2. 这样arr数组就可以写成打家劫舍问题的代码了

代码

cpp 复制代码
class Solution 
{
public:
    int arr[10001];
    int deleteAndEarn(vector<int>& nums) 
    {
        // 怎么达到不遍历可以删除其他数达到最大值呢?
        // 可以转化为自己熟悉的打家劫舍问题
        int n = nums.size();
        int ans = 0;
        for(int i = 0;i < n;i++)
        {
            arr[nums[i]] += nums[i];
            ans = max(ans,nums[i]);
        }
        
        if(n == 0) return 0;

        vector<int> f(ans+1);
        vector<int> g(ans+1);
        f[0] = arr[0],g[0] = 0;
        for(int i = 1;i <= ans;i++)
        {
            f[i] = g[i-1] + arr[i];
            g[i] = max(f[i-1],g[i-1]);
        }
        return max(f[ans],g[ans]);
    }
};

粉刷房子

题目链接

题解

  1. 红色是0,绿色是1,蓝色是2
  2. 可以分解为3个一维的线性dp,最后一个位置选红色,那么前一个位置的状态是选绿色和黄色中的最小值
  3. 同时填表,有三种颜色,n个房子,按线性dp的模式写

代码

cpp 复制代码
class Solution
{
public:
    int minCost(vector<vector<int>>& costs) 
    {
        int n = costs.size();
        vector<vector<int>> dp(n+1,vector<int>(3));// 0红 1绿 2蓝
        for(int i = 1;i < n+1;i++)
        {
            dp[i][0] = min(dp[i-1][1],dp[i-1][2]) + costs[i-1][0];
            dp[i][1] = min(dp[i-1][0],dp[i-1][2]) + costs[i-1][1];
            dp[i][2] = min(dp[i-1][1],dp[i-1][0]) + costs[i-1][2];
        }
        return min(min(dp[n][0],dp[n][1]),dp[n][2]);
    }
};

总结

  1. 多状态一般可以分为三种状态
  2. 分析出状态表示基本上就很好些了
  3. 状态转移方程为三个线性的dp,分析前一个转态,填写现在这个状态
相关推荐
乐迪信息28 分钟前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
Sirens.1 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
和裕2 小时前
全纸结构重型纸箱能否满足 1 吨以上设备出口熏蒸豁免要求?通关合规性全解析
大数据·运维·网络·人工智能·算法
tangguofeng2 小时前
不带头结点的链队操作集(不含InitFlag)(C语言版)
算法
苏打豆4 小时前
CRISP源码阅读——基于ROS2力矩反馈控制器与速度加速度零空间
c++·线性代数·算法·矩阵·机器人
蛋蛋的就会顺顺的4 小时前
hot100——矩阵
java·数据结构·算法·leetcode·力扣
老歌老听老掉牙4 小时前
麻花钻切屑形态演变的力学机制与临界条件分析
python·算法·钻头
zhangfeng11335 小时前
国产GPU/AI算力芯片现状(修订完整版 · 截至2026年9月
人工智能·算法·ai编程·npu
学代码的CJY5 小时前
从代码出发理解时间复杂度与空间复杂度
数据结构·算法
白帽攻防录5 小时前
SRC 挖洞:WSO2 JWT 算法混淆绕过深度复盘,CVE-2026-5430 不支持的算法怎么变成管理员
网络·算法·安全·网络安全·jwt