【动态规划】简单多状态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]));
    }
}
相关推荐
Jerry5 小时前
LeetCode 189. 轮转数组
算法
Jerry5 小时前
LeetCode 739. 每日温度
算法
2601_9545267510 小时前
【工业传感与算法实战】温漂补偿与零点抗漂破局:基于二阶多项式拟合的 C/C++ 边缘校准算法,深度拆解“压力变送器什么牌子好”的技术硬指标
c语言·c++·算法
叩码以求索11 小时前
浅谈:算法萌新如何高效刷题应对面试(一)
算法·面试·职场和发展
c2385612 小时前
把 C++ 内存分配拆透:new 与 malloc 的三层血缘
开发语言·c++·算法
aaaameliaaa13 小时前
指针之总结
c语言·笔记·算法
宵时待雨13 小时前
优选算法专题9:哈希表
数据结构·算法·散列表
txzrxz14 小时前
最短路问题——Dijkstra 算法
数据结构·c++·算法·最短路·优先队列
gwf21614 小时前
磨损均衡算法(Wear Leveling)——SSD如何让每块闪存“公平退休“?
运维·数据库·人工智能·python·嵌入式硬件·算法·智能硬件
noipp14 小时前
推荐题目:洛谷 P6231 [JSOI2013] 公交系统
c语言·数据结构·c++·算法·游戏·洛谷·luogu