Skip to content

Commit

Permalink
Merge pull request #497 from HuangFuSL/leetcode-250221
Browse files Browse the repository at this point in the history
Update: Leetcode 250221
  • Loading branch information
github-actions[bot] authored Feb 21, 2025
2 parents 7d1a317 + 6c4fb67 commit d4fe8c5
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/coding/leetcode/.pages
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ nav:
- 2051-2100:
- 2080. 区间内查询数字的频率: 2080.md
- 2201-2250:
- 2209. 用地毯覆盖后的最少白色砖块: 2209.md
- 2218. 从栈中取出 K 个硬币的最大面值和: 2218.md
- 2239. 找到最接近 0 的数字: 2239.md
- 2241. 设计一个 ATM 机器: 2241.md
Expand Down
114 changes: 114 additions & 0 deletions docs/coding/leetcode/2209.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
tags:
- 字符串
- 动态规划
- 前缀和
category: leetcode
difficulty: 困难
---

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

{{ display_difficulty(page.meta.difficulty) }}

## 题目

给你一个下标从 **0** 开始的 **二进制** 字符串 `floor` ,它表示地板上砖块的颜色。

* `floor[i] = '0'` 表示地板上第 `i` 块砖块的颜色是 **黑色**
* `floor[i] = '1'` 表示地板上第 `i` 块砖块的颜色是 **白色**

同时给你 `numCarpets``carpetLen` 。你有 `numCarpets`**黑色** 的地毯,每一条 **黑色** 的地毯长度都为 `carpetLen` 块砖块。请你使用这些地毯去覆盖砖块,使得未被覆盖的剩余 **白色** 砖块的数目 **最小** 。地毯相互之间可以覆盖。

请你返回没被覆盖的白色砖块的 **最少** 数目。

**示例 1:**

![](https://assets.leetcode.com/uploads/2022/02/10/ex1-1.png)

> 输入:floor = "10110101", numCarpets = 2, carpetLen = 2
>
> 输出:2
>
> 解释:
>
> 上图展示了剩余 2 块白色砖块的方案。
>
> 没有其他方案可以使未被覆盖的白色砖块少于 2 块。
**示例 2:**

![](https://assets.leetcode.com/uploads/2022/02/10/ex2.png)

> 输入:floor = "11111", numCarpets = 2, carpetLen = 3
>
> 输出:0
>
> 解释:
>
> 上图展示了所有白色砖块都被覆盖的一种方案。
>
> 注意,地毯相互之间可以覆盖。
**提示:**

* `1 <= carpetLen <= floor.length <= 1000`
* `floor[i]` 要么是 `'0'` ,要么是 `'1'`
* `1 <= numCarpets <= 1000`

[Reference](https://leetcode.cn/problems/minimum-white-tiles-after-covering-with-carpets)

## 题解

使用动态规划,定义`dp[i][j]`为从第`i`块砖开始,使用`j`条地毯,所能覆盖的最多白色砖块数,设地毯长度为$L$。则有状态转移方程:

$$
\text{dp}[i][j] = \max(\text{dp}[i + L][j - 1] + \sum_{k=i}^{i + L - 1} \text{floor}[k], \text{dp}[i + 1][j])
$$

以上算法需要重复计算一个地毯覆盖区间内白色砖块的数量。可以使用前缀和优化区间求和的过程,使用一个数组存储从第`i`块砖开始,到第`i + L`块砖结束,白色砖块的数量。

```python
class Solution:
def dfs(
self, dp: List[List[Optional[int]]], range_whites: List[int],
floor: str, currentPos: int, numCarpets: int, carpetLen: int, length: int
):
while dp[currentPos][numCarpets] is None:
if numCarpets == 0:
dp[currentPos][numCarpets] = 0
break
if length - currentPos <= carpetLen:
dp[currentPos][numCarpets] = sum(map(int, floor[currentPos:]))
break
place = self.dfs(
dp, range_whites, floor,
currentPos + carpetLen, numCarpets - 1, carpetLen, length
) + range_whites[currentPos]
not_place = self.dfs(
dp, range_whites, floor,
currentPos + 1, numCarpets, carpetLen, length
)
dp[currentPos][numCarpets] = max(place, not_place)

return dp[currentPos][numCarpets]

def minimumWhiteTiles(self, floor: str, numCarpets: int, carpetLen: int) -> int:
length = len(floor)
dp = [
[None] * (numCarpets + 1)
for i in range(length + 1)
]
range_whites = [0] * (length + 1)
for i in range(length - 1, -1, -1):
range_whites[i] = range_whites[i + 1]
if floor[i] == '1':
range_whites[i] += 1
if (i + carpetLen < length) and floor[i + carpetLen] == '1':
range_whites[i] -= 1

sum_whites = sum(map(int, floor))
return sum_whites - self.dfs(
dp, range_whites, floor, 0, numCarpets, carpetLen, length
)
```

0 comments on commit d4fe8c5

Please sign in to comment.