刷题的日常-粉刷房子

110 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

刷题的日常

一天一题,保持脑子清爽

粉刷房子

来自leetcode的 剑指 Offer II 091 题,题意如下:

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

给出的例子有:

输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。
     最少花费: 2 + 5 + 3 = 10

理解题意

题目不难,可以将条件提取出来:

  • 题目会给出一个数组
  • 给定的数组里面还是个数组,这层数组固定有三个值,代表粉刷不同颜色的费用
  • 要找出不同代价最低的粉刷方案
  • 注意:相邻的房子颜色不能相同

做题思路

一开始没注意相邻房子的颜色不能相同,直接获取代价最低的数字做了汇总,惨痛。
这一题其实可以用动态规划去做。从最上面出发,每层汇总最低代价,除开颜色相同的,最终把三层中最低的代价返回即可。

代码实现

代码实现也很简单,如下:

public class Solution {
    public int minCost(int[][] costs) {
        int result = Integer.MAX_VALUE, min;
        for (int i : costs[0]) {
            result = Math.min(result, i);
        }
        for (int i = 1; i < costs.length; i++) {
            int[] cost = costs[i];
            int[] pre = costs[i - 1];
            for (int j = 0; j < cost.length; j++) {
                min = Integer.MAX_VALUE;
                for (int p = 0; p < pre.length; p++) {
                    if (p == j) {
                        continue;
                    }
                    min = Math.min(min, pre[p]);
                }
                cost[j] = cost[j] + min;
            }
        }
        result = Integer.MAX_VALUE;
        for (int j : costs[costs.length - 1]) {
            result = Math.min(result, j);
        }
        return result;
    }
}