【动态规划】简单多状态dp问题:按摩师,打家劫舍,删除并获得点数,粉刷房子,买卖股票的最佳时机

文章目录

1. 按摩师 (面试题17.16)

按摩师

题目描述

解题思路

  • 状态表示:到第i个元素累计最长时间为dp[i]。对于每个元素都可以选择接受或不接受。需要两个数组来表示:f[i]表示接受当前预约的最长时间,g[i]表示不接受当前预约的最长时间
  • 状态转移方程:
    • 如果接受i预约,前一个一定不接受。f[i] = g[i-1] + nums[i]
    • 如果不接受,前一个预约可能接受,也可能不接受。取最大值。 g[i] = max(f[i-1],g[i-1])
  • 初始化:如果第一预约接受,f[0] = nums[0];不接受则g[i] =0

代码实现

java 复制代码
class Solution {
    public int massage(int[] nums) {
        int n = nums.length;
        if(n==0)
            return 0;
        int[] f = new int[n];
        int[] g = new int[n];
        f[0] = nums[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]);
    }
}

2. 打家劫舍II(LC 213)

打家劫舍II

题目描述

解题思路

分类讨论,把环形问题转换为线性问题。

  • 如果偷0号位置,则1号和n-号不可以偷,2号到n-2号可以偷,变成了上一题的解法
  • 如果不偷0号位置,则1号到n-号可以偷。

代码实现

java 复制代码
class Solution {
    int[] nums;
    public int rob(int[] _nums) {
        nums = _nums;
        int n = nums.length;

        int case1 = rob1(2,n-2,n) + nums[0];
        int case2 = rob1(1,n-1,n);
        return Math.max(case1,case2);
    }

    int rob1(int l,int r,int n){
        if(l>r)
            return 0;

        int[] f = new int[n];
        int[] g = new int[n];
        f[l] = nums[l];

        for(int i = l;i<=r;i++){
            f[i] = g[i-1]+nums[i];
            g[i] = Math.max(f[i-1],g[i-1]);
        }
        return Math.max(f[r],g[r]);
    }
}

3. 删除并获得点数(LC 740)

删除并获得点数

题目描述

解题思路

用数组hash记录每个数字出现的次数。这样就转换为第一个题,用两个数组表示当前数字删或不删得到的总和。

代码实现

java 复制代码
class Solution {
    public int deleteAndEarn(int[] nums) {
        int[] hash = new int[10001];
        int max = 0;
        for(int num:nums){
            hash[num]++;
            max = Math.max(max,num);
        }

        int[] f = new int[max+1];
        int[] g = new int[max+1];

        g[1] = hash[1];

        for(int i = 2;i<=max;i++){
            f[i] =  Math.max(g[i-1],f[i-1]);
            g[i] =f[i-1] + hash[i]*i;
        }
        return Math.max(f[max],g[max]);
    }
}

4. 粉刷房子(LCR091)

粉刷房子

题目描述

解题思路

与第一题类似,只需要用三个数组做动态规划即可

代码实现

java 复制代码
class Solution {
    public int minCost(int[][] costs) {
        int n = costs.length;
        int[] red = new int[n];
        int[] blue = new int[n];
        int[] green = new int[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] = Math.min(green[i-1],blue[i-1])+costs[i][0];
            blue[i] = Math.min(green[i-1],red[i-1])+costs[i][1];
            green[i] = Math.min(red[i-1],blue[i-1])+costs[i][2];
        }
        return Math.min(green[n-1],Math.min(red[n-1],blue[n-1]));
    }
}
相关推荐
Dumbness27 分钟前
UIA 读微信群消息没有 id,怎么判断哪条是新的:后缀对齐在翻历史和撤回时整屏重报
python·算法
taka28 分钟前
从 24x 到 141x:我用纯 Python 零依赖项目,扒开了 GPU 加速的性能黑洞
算法
UIU1141 小时前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
旖旎夜光1 小时前
LeetCode 315: 算右侧小于当前元素的个数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法
像风一样自由20201 小时前
2.如何用FastAPI把一个Python算法封装成HTTP服务
python·算法·fastapi
D e re k ZH1 小时前
保序回归:从 PAVA 到可并堆的单调约束优化
c++·算法·数据挖掘·回归·kotlin
青少儿编程课堂1 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:字典树前缀树与单词检索统计
c++·python·算法·bfs·信息学竞赛
Nuanyt1 小时前
LeetCode Hot 100 链表专题2 3 题 (Java)
java·笔记·算法·leetcode·链表
海绵宝宝转agent2 小时前
LeetCodehot100题解
java·笔记·学习·算法·leetcode·深度优先
青少儿编程课堂2 小时前
2026蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:堆排序与优先队列解析
c++·python·算法·bfs·信息学竞赛