普通视图

发现新文章,点击刷新页面。
昨天 — 2025年2月21日首页

贪心 && DP C++

作者 Cyber-Space
2022年3月20日 00:13

dp[i][j] 表示考虑前面长度为 j 的地板中,用了 i 条地毯,最后剩余最少白色砖块。
状态转移方程

  1. i == 0 时,此时不用地毯, dp[0][j] 表示前 j 个砖块中白色砖块数目。
  2. i != 0 时,dp[i][j] = min(dp[i][j - 1] + count[j], dp[i - 1][j - carpetLen]);
    其中 count[j] 表示第 j 块地板是否为白色砖块,
  • dp[i][j-1] + count[j] 表示前 j - 1 块地板用了i 条地毯,剩余最少的白色砖块,加上第 j 块地板是否为白色砖块。(即第 j 个位置不用地毯)
  • dp[i - 1][j - carpetLen] 表示在下标 j 这里用了地毯,那么 dp[i][j] 就和前 (j - carpetLen) 块地板中用了 i - 1 条地毯剩余的白色砖块数目一致。(即第 j 个位置用了地毯)

时间复杂度: O(nm)
空间复杂度: O(n
m)
其中 n 为 floor 长度, m 为numcarpets

代码如下:

class Solution {
public:
    int minimumWhiteTiles(string floor, int numCarpets, int carpetLen) {
        int len = floor.size();
        vector<vector<int>> dp(numCarpets + 1, vector<int>(len, 0));
        vector<int> count(len); //第j块地板是否为白色
        dp[0][0] = floor[0] == '1' ? 1 : 0;
        for(int i = 1; i < len; ++i) {
            dp[0][i] = dp[0][i - 1];
            if(floor[i] == '1') dp[0][i]++, count[i] = 1;
        }
        for(int i = 1; i <= numCarpets; ++i) {
            for(int j = 0; j < len; ++j) {
                if(j < carpetLen) dp[i][j] = 0; //少于carpetLen块砖块用了地毯最终都会剩余0块白色砖块
                else dp[i][j] = min(dp[i][j - 1] + count[j], dp[i - 1][j - carpetLen]);
            }
        }
        return dp[numCarpets][len - 1];
    }
};
❌
❌