2742.给墙壁刷漆

76 阅读2分钟

题目

Leetcode链接 给你两个长度为 n 下标从 0 开始的整数数组 cost 和 time ,分别表示给 n 堵不同的墙刷油漆需要的开销和时间。你有两名油漆匠:

  • 一位需要 付费 的油漆匠,刷第 i 堵墙需要花费 time[i] 单位的时间,开销为 cost[i] 单位的钱。
  • 一位 免费 的油漆匠,刷 任意 一堵墙的时间为 1 单位,开销为 0 。但是必须在付费油漆匠 工作 时,免费油漆匠才会工作。

请你返回刷完 n 堵墙最少开销为多少。

示例1

  • 输入: cost = [1,2,3,2], time = [1,2,3,2]
  • 输出:3

示例2

  • 输入:cost = [2,3,4,2], time = [1,1,1,1]
  • 输出:4

提示

  • 1 <= cost.length <= 500
  • cost.length == time.length
  • 1 <= cost[i] <= 106
  • 1 <= time[i] <= 500

题解

分析:免费油漆匠的工作效率更高,但是免费的油漆匠是根据收费油漆匠的工作时间决定的。因此一个收费油漆匠能刷 time[i](免费油漆匠刷的墙) + 1(收费油漆匠刷的墙),因此可以将问题看成一个 0-1 背包问题。

0-1 背包模板

int n;  // 物品个数
int c;  // 背包容量
int[] v;  // v[i] 表示第 i 个物品的价值
int[] w;  // w[i] 表示第 i 个物品的重量
int[] dp = new int[c + 1];
// 初始化
dp[x] = ...
// 状态转移
for (int i = 1; i <= n; i++) {
    for (int j = c; j >= w[i - 1] ; j--) {
        dp[j] = Math.max(dp[j], dp[j - w[i - 1]] + v[i - 1]);
    }
}
return dp[c];

当前问题:要求最小花费,cost 对应 v,需要将 Math.max 变成 Math.min,重量对应 time。

代码

class Solution {
    public int paintWalls(int[] cost, int[] time) {
        int len = cost.length;
        int[] dp = new int[len+1];
        Arrays.fill(dp, Integer.MAX_VALUE/5);
        dp[0] = 0;
        for (int i = 0; i < len; i++) {
            for (int j = len; j > 0; j--) {
                // 在选或不选油漆匠之间选择花费小的一个
                dp[j] = Math.min(dp[j], dp[Math.max(j - time[i] - 1, 0)] + cost[i]);
            }
        }
        return dp[len];
    }
}