力扣 2209 🟥用地毯覆盖后的最少白色砖块

警告
本文最后更新于 2022-09-02,文中内容可能已过时。

2209. 用地毯覆盖后的最少白色砖块

$dp[i][j]$ 表示用 $i$ 块地毯铺前 $j$ 块砖块剩余最少白色砖块数量。

不使用地毯,则前 $j$ 块砖块剩余最少白色砖块数量为白色砖块的数量。

$$ dp[0][j] = dp[0][j - 1] + I(s[j] == ‘1’) $$

  • 不铺地毯:若第 $i$ 块砖块为白色砖块,则剩余白色砖块数量加一。
  • 铺地毯:用一个地毯覆盖砖块,并且其末尾刚好覆盖住第 $i$ 块砖块。

$$ dp[i][j] = \min(dp[i - 1][j] + I(s[j] == ‘1’), dp[i - len][j - 1]) $$

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
    public int minimumWhiteTiles(String floor, int numCarpets, int carpetLen) {
        int n = floor.length();
        // 能够覆盖所有砖块
        if (numCarpets * carpetLen >= n) return 0;
        // dp[i][j] 表示用 i 块地毯覆盖前 j 块砖块剩余最少白色砖块数量。
        int[][] dp = new int[numCarpets + 1][n];
        // 不铺地毯时前 j 块砖块剩余最少白色砖块数量为前 j 块砖块中白色砖块的数量。
        dp[0][0] = floor.charAt(0) == '1' ? 1 : 0;
        for (int j = 1; j < n; j++)
            dp[0][j] = dp[0][j - 1] + (floor.charAt(j) == '1' ? 1 : 0);
        // 不铺地毯时,若第 j 块砖块为白色砖块,则剩余白色砖块数量加一。
        // 铺地毯时,用地毯的边缘覆盖第 j 块砖块。
        // 当铺第 i 块地毯时,至少可以覆盖 i * carpetLen 块砖块,所以少于。
        for (int i = 1; i <= numCarpets; i++)
            for (int j = i * carpetLen; j < n; j++)
                dp[i][j] = Math.min(dp[i][j - 1] + (floor.charAt(j) == '1' ? 1 : 0), dp[i - 1][j - carpetLen]);
        // 返回用 numCarpets 块地毯覆盖前 n - 1 块砖块剩余最少白色砖块数量。
        return dp[numCarpets][n - 1];
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public int minimumWhiteTiles(String floor, int numCarpets, int carpetLen) {
        int n = floor.length();
        if (numCarpets * carpetLen >= n) return 0;
        int[] pre = new int[n];
        int[] cur = new int[n];
        pre[0] = floor.charAt(0) == '1' ? 1 : 0;
        for (int i = 1; i < n; i++)
            pre[i] = pre[i - 1] + (floor.charAt(i) == '1' ? 1 : 0);
        for (int i = 1; i <= numCarpets; i++) {
            cur[i * carpetLen - 1] = 0; // 设置起点为 0
            for (int j = i * carpetLen; j < n; j++)
                cur[j] = Math.min(cur[j - 1] + (floor.charAt(j) == '1' ? 1 : 0), pre[j - carpetLen]);
            int[] tmp = cur; // 交换,避免创建新数组
            cur = pre;
            pre = tmp;
        }
        return pre[n - 1];
    }
}
  1. 动态规划的典型思考策略(Python/Java/C++/Go) - 用地毯覆盖后的最少白色砖块 - 力扣(LeetCode)