首页 > 其他分享 >【DP】LeetCode 256. 粉刷房子

【DP】LeetCode 256. 粉刷房子

时间:2023-04-03 09:55:13浏览次数:55  
标签:min int 粉刷 房子 costs 刷成 256 LeetCode DP

题目链接

256. 粉刷房子

假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。
例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。
请计算出粉刷完所有房子最少的花费成本。
示例 1:
输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。
最少花费: 2 + 5 + 3 = 10。
示例 2:
输入: costs = [[7,6,2]]
输出: 2

思路

分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律

表示状态

本题与常规题目不同的一点:本题需要记录三种情况下的花费,因为你不知道每个房子最终会被刷成什么颜色。什么意思呢?举个栗子:

  • 第 n 个房子刷成了红色,那么第 n-1 个房子就要刷成蓝色或绿色,此时需要存储第 n 个房子刷成红色情况下的花费
  • 第 n 个房子刷成了蓝色,那么第 n-1 个房子就要刷成红色或绿色,此时需要存储第 n 个房子刷成蓝色情况下的花费
  • 第 n 个房子刷成了绿色,那么第 n-1 个房子就要刷成蓝色或红色,此时需要存储第 n 个房子刷成绿色情况下的花费

既然我们要存储三份信息,索性就直接定义三个数组 redDPblueDPgreenDP 分别存储第 i 个房子刷成某种颜色情况下的花费。

找状态转移方程

还是从最终阶段出发,

  • 第 n 个房子是红色,说明第 n-1 个房子是蓝色或绿色,此时到第 n 个房子的总花费为 \(min(blueDP[n-1], greenDP[n-1]) + cost[n][0]\)
  • 第 n 个房子是蓝色,说明第 n-1 个房子是红色或绿色,此时到第 n 个房子的总花费为 \(min(redDP[n-1], greenDP[n-1]) + cost[n][1]\)
  • 第 n 个房子是绿色,说明第 n-1 个房子是蓝色或红色,此时到第 n 个房子的总花费为 \(min(blueDP[n-1], redDP[n-1]) + cost[n][2]\)

边界处理

很容易知道

redDP[0] = costs[0][0];
blueDP[0] = costs[0][1];
greenDP[0] = costs[0][2];

空间优化

因为每个数组的第 i 项只与第 i-1 项有关,所以只需要三个单变量分别表示第 i-1 项,循环滚动更新就行。

代码

dp数组版

class Solution {
    public int minCost(int[][] costs) {
        if(costs.length == 0){
            return 0;
        }

        int n = costs.length;
        // 第 i 个房子刷成红色情况下的最小花费
        int[] redDP = new int[n];
        // 第 i 个房子刷成蓝色情况下的最小花费
        int[] blueDP = new int[n];
        // 第 i 个房子刷成绿色情况下的最小花费
        int[] greenDP = new int[n];

        redDP[0] = costs[0][0];
        blueDP[0] = costs[0][1];
        greenDP[0] = costs[0][2];

        for(int i = 1; i < n; i++){
            redDP[i] = Math.min(blueDP[i - 1], greenDP[i - 1]) + costs[i][0];
            blueDP[i] = Math.min(redDP[i - 1], greenDP[i - 1]) + costs[i][1];
            greenDP[i] = Math.min(blueDP[i - 1], redDP[i - 1]) + costs[i][2];
        }

        return Math.min(Math.min(redDP[n - 1], blueDP[n - 1]), greenDP[n - 1]);
    }
}

空间优化版

class Solution {
    public int minCost(int[][] costs) {
        if(costs.length == 0){
            return 0;
        }

        int n = costs.length;
        int redCost = costs[0][0];
        int blueCost = costs[0][1];
        int greenCost = costs[0][2];

        for(int i = 1; i < n; i++){
            int newRedCost = Math.min(blueCost, greenCost) + costs[i][0];
            int newBlueCost = Math.min(redCost, greenCost) + costs[i][1];
            int newGreenCost = Math.min(redCost, blueCost) + costs[i][2];

            redCost = newRedCost;
            blueCost = newBlueCost;
            greenCost = newGreenCost;
        }

        return Math.min(Math.min(redCost, blueCost), greenCost);
    }
}

标签:min,int,粉刷,房子,costs,刷成,256,LeetCode,DP
From: https://www.cnblogs.com/shixuanliu/p/17282137.html

相关文章

  • leetcode题中的逆向思维——集锦
    417.太平洋大西洋水流问题虽然题目要求的是满足向下流能到达两个大洋的位置,如果我们对所有的位置进行搜索,那么在不剪枝的情况下复杂度会很高。因此我们可以反过来想,从两个大洋开始向上流,这样我们只需要对矩形四条边进行搜索。搜索完成后,只需遍历一遍矩阵,满足条件的位置即为两个......
  • 树形DP——小红树
    题目描述小红拿到了一棵树,每个节点被染成了红色或者蓝色。小红定义每条边的权值为:删除这条边时,形成的两个子树的同色连通块数量之差的绝对值。小红想知道,所有边的权值之和是多少?输入描述第一行输入一个正整数n,代表节点的数量。第二行输入一个长度为n且仅由'R'和'B'两种字......
  • leetcode 394.字符串解码 Java
    394.字符串解码给定一个经过编码的字符串,返回它解码后的字符串。编码规则为:k[encoded_string],表示其中方括号内部的encoded_string正好重复k次。注意k保证为正整数。你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。此外......
  • leetcode 739.每日的温度 Java
    739.每日的温度给定一个整数数组temperatures,表示每天的温度,返回一个数组answer,其中answer[i]是指对于第i天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用0来代替。示例1:输入:temperatures=[73,74,75,71,69,72,76,73]输出:[1,1,4,2,1,......
  • leetcode 20. 有效的括号 Java
    给定一个只包括'(',')','{','}','[',']'的字符串s,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号。示例1:输入:s="()"输出:true示例2:输入:s="()[]{}"输出:true......
  • Leetcode(剑指offer专项训练)——DP专项(6)
    排序的数目题目给定一个由不同 正整数组成的数组nums,和一个目标整数target。请从nums中找出并返回总和为target的元素组合的个数。数组中的数字可以在一次排列中出现任意次,但是顺序不同的序列被视作不同的组合。题目数据保证答案符合32位整数范围。链接无效DFS......
  • Leetcode(剑指offer专项训练)——DP专项(5)
    最少的硬币数目给定不同面额的硬币coins和一个总金额amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。你可以认为每种硬币的数量是无限的。链接完全背包问题思路:主要是要自己推出动态转移方程\[F(i)=mi......
  • 【DP】LeetCode 64. 最小路径和
    题目链接64.最小路径和思路分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律表示状态假设到了右下角,考虑一下我们要存储的信息走到最后坐标的最小步数当前坐标的信息,用来判断是否走到了右下角很容易联想到使用......
  • 【DP】LeetCode 70. 爬楼梯
    题目链接70.爬楼梯思路分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律表示状态假设走到了最后一层台阶,考虑一下我们要存储的信息:走到这最后一层台阶的方法数当前台阶数,用于判断是否走到了最后一层台阶这时候......
  • [LeetCode] 1338. Reduce Array Size to The Half 数组大小减半
    Youaregivenanintegerarray arr.Youcanchooseasetofintegersandremovealltheoccurrencesoftheseintegersinthearray.Return theminimumsizeofthesetsothat atleast halfoftheintegersofthearrayareremoved.Example1:Input:arr=......