You are given a 0-indexed binary string floor, which represents the colors of tiles on a floor:
floor[i] = '0' denotes that the ith tile of the floor is colored black.
On the other hand, floor[i] = '1' denotes that the ith tile of the floor is colored white.
You are also given numCarpets and carpetLen. You have numCarpetsblack carpets, each of length carpetLen tiles. Cover the tiles with the given carpets such that the number of white tiles still visible is minimum. Carpets may overlap one another.
Return the minimum number of white tiles still visible.
Example 1:
Input: floor = "10110101", numCarpets = 2, carpetLen = 2
Output: 2
Explanation:
The figure above shows one way of covering the tiles with the carpets such that only 2 white tiles are visible.
No other way of covering the tiles with the carpets can leave less than 2 white tiles visible.
Example 2:
Input: floor = "11111", numCarpets = 2, carpetLen = 3
Output: 0
Explanation:
The figure above shows one way of covering the tiles with the carpets such that no white tiles are visible.
Note that the carpets are able to overlap one another.
Constraints:
1 <= carpetLen <= floor.length <= 1000
floor[i] is either '0' or '1'.
1 <= numCarpets <= 1000
Solutions
Solution 1: Memoization Search
Thinking
We have \(m\) carpets of length \(L\) and want as few uncovered white tiles as possible. Enumerating placements is exponential; \(n, m \le 10^3\) forbids that. Decisions can be made left to right.
Let \(\textit{dfs}(i, j)\) be the fewest uncovered white tiles from index \(i\) with \(j\) carpets left. A black tile is skipped. With no carpet left, the remainder is the prefix-sum difference \(s[n]-s[i]\). On a white tile we either leave it (\(1 + \textit{dfs}(i+1, j)\)) or cover it (\(\textit{dfs}(i+L, j-1)\)).
There are \(O(nm)\) states and constant work each; memoization yields \(\textit{dfs}(0, m)\).
We design a function \(\textit{dfs}(i, j)\) to represent the minimum number of white tiles that are not covered starting from index \(i\) using \(j\) carpets. The answer is \(\textit{dfs}(0, \textit{numCarpets})\).
For index \(i\), we discuss the following cases:
If \(i \ge n\), it means all tiles have been covered, return \(0\);
If \(\textit{floor}[i] = 0\), then we do not need to use a carpet, just skip it, i.e., \(\textit{dfs}(i, j) = \textit{dfs}(i + 1, j)\);
If \(j = 0\), then we can directly use the prefix sum array \(s\) to calculate the number of remaining uncovered white tiles, i.e., \(\textit{dfs}(i, j) = s[n] - s[i]\);
If \(\textit{floor}[i] = 1\), then we can choose to use a carpet or not, and take the minimum of the two, i.e., \(\textit{dfs}(i, j) = \min(\textit{dfs}(i + 1, j), \textit{dfs}(i + \textit{carpetLen}, j - 1))\).
We use memoization search to solve this problem.
The time complexity is \(O(nm)\), and the space complexity is \(O(nm)\), where \(n\) and \(m\) are the length of the string \(\textit{floor}\) and the value of \(\textit{numCarpets}\), respectively.
We have \(m\) carpets of length \(L\) and want as few visible white tiles as possible. Enumerating every placement is exponential, and both \(n\) and \(m\) can be \(1000\).
A black tile always jumps to the next index. A floor of black tiles is a chain from \(0\) to \(n\) of length \(n\). Python raises RecursionError when \(n=1000\).
Skipping a black tile, leaving a white tile, or laying a carpet all read a later index. Laying a carpet also spends one carpet.
Fill from the right. \(f[i][j]\) is the fewest visible white tiles from index \(i\) with \(j\) carpets left, and \(f[n][\cdot]=0\). A black tile copies \(f[i+1][j]\). With no carpet left the answer is the remaining white count \(s[n]-s[i]\). A white tile takes the minimum of leaving it, \(1+f[i+1][j]\), and covering it, \(f[i+L][j-1]\).
Let \(s[i]\) be the number of white tiles in the first \(i\) positions of \(\textit{floor}\). Let \(f[i][j]\) be the fewest white tiles left visible from index \(i\) with \(j\) carpets remaining. The answer is \(f[0][\textit{numCarpets}]\). Set \(f[n][j] = 0\), which means every tile has already been passed.
Fill \(i\) from \(n - 1\) down to \(0\) and \(j\) from \(0\) through \(m\):
If \(\textit{floor}[i] = 0\), the tile is black and costs no carpet, so \(f[i][j] = f[i + 1][j]\).
If \(j = 0\), no carpet remains, so \(f[i][j] = s[n] - s[i]\).
Otherwise the tile is white. Leaving it visible costs \(1 + f[i + 1][j]\). Laying a carpet of length \(L\) jumps to index \(i + L\) and leaves \(j - 1\) carpets. That branch is \(f[i + L][j - 1]\) when \(i + L \le n\), and \(0\) when the jump passes the end of the floor. \(f[i][j]\) is the smaller of the two.
The time complexity is \(O(nm)\), and the space complexity is \(O(nm)\), where \(n\) and \(m\) are the length of \(\textit{floor}\) and the value of \(\textit{numCarpets}\).