《算法题讲解指南:动态规划算法--简单多状态dp问题》--13.删除并获得点数,14.粉刷房子

🔥小叶-duck个人主页

❄️个人专栏《Data-Structure-Learning》《C++入门到进阶&自我学习过程记录》
《算法题讲解指南》--优选算法
《算法题讲解指南》--递归、搜索与回溯算法
《算法题讲解指南》--动态规划算法

未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游


目录

13.删除并获得点数

题目链接:

题目描述:

题目示例:

解法(动态规划):

算法思路:

C++算法代码:

算法总结及流程解析:

14.粉刷房子

题目链接:

题目描述:

题目示例:

解法(动态规划):

算法思路:

C++算法代码:

算法总结及流程解析:

结束语


13.删除并获得点数

题目链接:

740. 删除并获得点数 - 力扣(LeetCode)

题目描述:

题目示例:

解法(动态规划):

算法思路:

其实这道题依旧是「打家劫舍」问题的变型。

我们注意到题目描述,选择 x 数字的时候,x-1 与 x+1 是不能被选择的。像不像「打家劫舍」问题中,选择 i 位置的金额之后,就不能选择 i - 1 位置以及 i + 1 位置的金额呢?

因此,我们可以创建一个大小为 10001 (根据题目的数据范围)的 hash 数组,将 nums 数组中每一个元素 x,累加到 hash 数组下标为 x 的位置处,然后在 hash 数组上来一次「打家劫舍」即可。

C++算法代码:

cpp 复制代码
class Solution {
public:
    int deleteAndEarn(vector<int>& nums) 
    {
        //统计每个数字出现的次数,放到一个数组中
        int arr[10001] = { 0 };
        for(int i = 0; i < nums.size(); i++)
        {
            arr[nums[i]]++;
        }   

        vector<int> f(10001);//f[i]表示在arr中第i个位置选择删除并获得点数,此时获得的最大点数
        vector<int> g(10001);//g[i]表示在arr中第i个位置不选择删除并获得点数,此时获得的最大点数
        f[1] = arr[1] * 1;
        for(int i = 2; i < 10001; i++)
        {
            f[i] = g[i - 1] + arr[i] * i;
            g[i] = max(f[i - 1], g[i - 1]);
        }
        return max(f[10000], g[10000]);
    }
};

算法总结及流程解析:

14.粉刷房子

题目链接:

LCR 091. 粉刷房子 - 力扣(LeetCode)

题目描述:

题目示例:

解法(动态规划):

算法思路:

1.状态表示:

对于线性dp,我们可以用「经验+题目要求」来定义状态表示:

i.以某个位置为结尾,巴拉巴拉;

ii.以某个位置为起点,巴拉巴拉。

这里我们选择比较常用的方式,以某个位置为结尾,结合题目要求,定义一个状态表示:

但是我们这个题在i位置的时候,会面临「红」「蓝」「绿」三种抉择,所依赖的状态需要细

分:

dp[i][0]表示:粉刷到i位置的时候,最后一个位置粉刷上「红色」,此时的最小花费;

dp[i][1]表示:粉刷到i位置的时候,最后一个位置粉刷上「蓝色」,此时的最小花费;

dp[i][2]表示:粉刷到i位置的时候,最后一个位置粉刷上「绿色」,此时的最小花费。

2.状态转移方程:

因为状态表示定义了三个,因此我们的状态转移方程也要分析三个:

对于dp[i][0]:

如果第i个位置粉刷上「红色」,那么i-1位置上可以是「蓝色」或者「绿色」。因此我们需要知道粉刷到i-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][0], dp[i - 1][1]) + costs[i - 1][2]。

3.初始化:

可以在最前面加上一个「辅助结点」,帮助我们初始化。使用这种技巧要注意两个点:

i.辅助结点里面的值要「保证后续填表是正确的」;

ii.「下标的映射关系」。

在本题中,添加一个节点,并且初始化为0即可。

4.填表顺序

根据「状态转移方程」得「从左往右,三个表一起填」。

5.返回值

根据「状态表示」,应该返回最后一个位置粉刷上三种颜色情况下的最小值,因此需要返回:

min(dp[n][0], min(dp[n][1], dp[n][2])) 。

C++算法代码:

cpp 复制代码
class Solution {
public:
    int minCost(vector<vector<int>>& costs) 
    {
        // //方法一:用三个一维dp数组实现动态规划:
        // int n = costs.size();
        // vector<int> red(n);
        // vector<int> blue(n);
        // vector<int> green(n);
        // red[0] = costs[0][0];
        // blue[0] = costs[0][1];
        // green[0] = costs[0][2];
        // for(int i = 1; i < n; i++)
        // {
        //     red[i] = min(blue[i - 1], green[i - 1]) + costs[i][0];
        //     blue[i] = min(red[i - 1], green[i - 1]) + costs[i][1];
        //     green[i] = min(red[i - 1], blue[i - 1]) + costs[i][2];
        // }
        // return min(min(red[n - 1], blue[n - 1]), green[n - 1]);

        //方法二:用一个二维dp数组实现动态规划:
        int n = costs.size();
        vector<vector<int>> dp(n, vector<int>(3));
        dp[0][0] = costs[0][0];
        dp[0][1] = costs[0][1];
        dp[0][2] = costs[0][2];
        for(int i = 1; i < n; i++)
        {
            dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0];
            dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1];
            dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2];
        }
        return min(min(dp[n - 1][0], dp[n - 1][1]), dp[n - 1][2]);
    }
};

算法总结及流程解析:

结束语

到此,13.删除并获得点数,14.粉刷房子 这两道算法题就讲解完了。**删除并获得点数,通过构建hash数组转化为打家劫舍问题,定义f[i]和g[i]分别表示选择/不选i位置时的最大点数,状态转移后取最大值。粉刷房子,建立dp[i][0-2]表示i位置刷红/蓝/绿的最小花费,通过比较前一个位置其他颜色的最小花费加上当前成本来更新状态,最终返回三种颜色的最小花费。**希望大家能有所收获!

相关推荐
W23035765737 小时前
经典算法:最长上升子序列(LIS)深度解析 C++ 实现
开发语言·c++·算法
.Ashy.7 小时前
2026.4.11 蓝桥杯软件类C/C++ G组山东省赛 小记
c语言·c++·蓝桥杯
minji...8 小时前
Linux 线程同步与互斥(三) 生产者消费者模型,基于阻塞队列的生产者消费者模型的代码实现
linux·运维·服务器·开发语言·网络·c++·算法
语戚9 小时前
力扣 968. 监控二叉树 —— 贪心 & 树形 DP 双解法递归 + 非递归全解(Java 实现)
java·算法·leetcode·贪心算法·动态规划·力扣·
skywalker_119 小时前
力扣hot100-7(接雨水),8(无重复字符的最长子串)
算法·leetcode·职场和发展
bIo7lyA8v10 小时前
算法稳定性分析中的输入扰动建模的技术9
算法
CoderCodingNo10 小时前
【GESP】C++三级真题 luogu-B4499, [GESP202603 三级] 二进制回文串
数据结构·c++·算法
sinat_2869451910 小时前
AI Coding 时代的 TDD:从理念到工程落地
人工智能·深度学习·算法·tdd
炽烈小老头10 小时前
【 每天学习一点算法 2026/04/12】x 的平方根
学习·算法