|
| 1 | +--- |
| 2 | +title: 3219.切蛋糕的最小总开销 II |
| 3 | +date: 2024-12-31 14:21:50 |
| 4 | +tags: [题解, LeetCode, 困难, 贪心, 数组, 排序] |
| 5 | +--- |
| 6 | + |
| 7 | +# 【LetMeFly】3219.切蛋糕的最小总开销 II:贪心——先切贵的 |
| 8 | + |
| 9 | +力扣题目链接:[https://leetcode.cn/problems/minimum-cost-for-cutting-cake-ii/](https://leetcode.cn/problems/minimum-cost-for-cutting-cake-ii/) |
| 10 | + |
| 11 | +<p>有一个 <code>m x n</code> 大小的矩形蛋糕,需要切成 <code>1 x 1</code> 的小块。</p> |
| 12 | + |
| 13 | +<p>给你整数 <code>m</code> ,<code>n</code> 和两个数组:</p> |
| 14 | + |
| 15 | +<ul> |
| 16 | + <li><code>horizontalCut</code> 的大小为 <code>m - 1</code> ,其中 <code>horizontalCut[i]</code> 表示沿着水平线 <code>i</code> 切蛋糕的开销。</li> |
| 17 | + <li><code>verticalCut</code> 的大小为 <code>n - 1</code> ,其中 <code>verticalCut[j]</code> 表示沿着垂直线 <code>j</code> 切蛋糕的开销。</li> |
| 18 | +</ul> |
| 19 | + |
| 20 | +<p>一次操作中,你可以选择任意不是 <code>1 x 1</code> 大小的矩形蛋糕并执行以下操作之一:</p> |
| 21 | + |
| 22 | +<ol> |
| 23 | + <li>沿着水平线 <code>i</code> 切开蛋糕,开销为 <code>horizontalCut[i]</code> 。</li> |
| 24 | + <li>沿着垂直线 <code>j</code> 切开蛋糕,开销为 <code>verticalCut[j]</code> 。</li> |
| 25 | +</ol> |
| 26 | + |
| 27 | +<p>每次操作后,这块蛋糕都被切成两个独立的小蛋糕。</p> |
| 28 | + |
| 29 | +<p>每次操作的开销都为最开始对应切割线的开销,并且不会改变。</p> |
| 30 | + |
| 31 | +<p>请你返回将蛋糕全部切成 <code>1 x 1</code> 的蛋糕块的 <strong>最小</strong> 总开销。</p> |
| 32 | + |
| 33 | +<p> </p> |
| 34 | + |
| 35 | +<p><strong class="example">示例 1:</strong></p> |
| 36 | + |
| 37 | +<div class="example-block"> |
| 38 | +<p><span class="example-io"><b>输入:</b>m = 3, n = 2, horizontalCut = [1,3], verticalCut = [5]</span></p> |
| 39 | + |
| 40 | +<p><span class="example-io"><b>输出:</b>13</span></p> |
| 41 | + |
| 42 | +<p><strong>解释:</strong></p> |
| 43 | + |
| 44 | +<p><img alt="" src="https://assets.leetcode.com/uploads/2024/06/04/ezgifcom-animated-gif-maker-1.gif" style="width: 280px; height: 320px;" /></p> |
| 45 | + |
| 46 | +<ul> |
| 47 | + <li>沿着垂直线 0 切开蛋糕,开销为 5 。</li> |
| 48 | + <li>沿着水平线 0 切开 <code>3 x 1</code> 的蛋糕块,开销为 1 。</li> |
| 49 | + <li>沿着水平线 0 切开 <code>3 x 1</code> 的蛋糕块,开销为 1 。</li> |
| 50 | + <li>沿着水平线 1 切开 <code>2 x 1</code> 的蛋糕块,开销为 3 。</li> |
| 51 | + <li>沿着水平线 1 切开 <code>2 x 1</code> 的蛋糕块,开销为 3 。</li> |
| 52 | +</ul> |
| 53 | + |
| 54 | +<p>总开销为 <code>5 + 1 + 1 + 3 + 3 = 13</code> 。</p> |
| 55 | +</div> |
| 56 | + |
| 57 | +<p><strong class="example">示例 2:</strong></p> |
| 58 | + |
| 59 | +<div class="example-block"> |
| 60 | +<p><span class="example-io"><b>输入:</b>m = 2, n = 2, horizontalCut = [7], verticalCut = [4]</span></p> |
| 61 | + |
| 62 | +<p><span class="example-io"><b>输出:</b>15</span></p> |
| 63 | + |
| 64 | +<p><strong>解释:</strong></p> |
| 65 | + |
| 66 | +<ul> |
| 67 | + <li>沿着水平线 0 切开蛋糕,开销为 7 。</li> |
| 68 | + <li>沿着垂直线 0 切开 <code>1 x 2</code> 的蛋糕块,开销为 4 。</li> |
| 69 | + <li>沿着垂直线 0 切开 <code>1 x 2</code> 的蛋糕块,开销为 4 。</li> |
| 70 | +</ul> |
| 71 | + |
| 72 | +<p>总开销为 <code>7 + 4 + 4 = 15</code> 。</p> |
| 73 | +</div> |
| 74 | + |
| 75 | +<p> </p> |
| 76 | + |
| 77 | +<p><strong>提示:</strong></p> |
| 78 | + |
| 79 | +<ul> |
| 80 | + <li><code>1 <= m, n <= 10<sup>5</sup></code></li> |
| 81 | + <li><code>horizontalCut.length == m - 1</code></li> |
| 82 | + <li><code>verticalCut.length == n - 1</code></li> |
| 83 | + <li><code>1 <= horizontalCut[i], verticalCut[i] <= 10<sup>3</sup></code></li> |
| 84 | +</ul> |
| 85 | + |
| 86 | + |
| 87 | + |
| 88 | +## 解题方法:贪心(双指针) |
| 89 | + |
| 90 | +从头到尾贯穿整个蛋糕的一刀切的越早,所需的切割次数越少。 |
| 91 | + |
| 92 | +> 例如假如一个2x2的蛋糕: |
| 93 | +> |
| 94 | +> 1. 先竖着切,就是竖着一刀横着两刀 |
| 95 | +> 2. 先横着切,就是竖着两刀横着一刀 |
| 96 | +
|
| 97 | +所以,将切割代价按照从大到小的顺序排序,然后在横竖切法里挑最贵的先切就好了。 |
| 98 | + |
| 99 | +切的时候从头切到尾: |
| 100 | + |
| 101 | +> 假如这是竖着的一刀,就看横向一共切了几次。 |
| 102 | +> |
| 103 | +> 如果横向一共切了$hCutTime$次,那么这一刀就要切$hCutTime + 1$次。 |
| 104 | +
|
| 105 | ++ 时间复杂度$O(m\log m + n\log n)$ |
| 106 | ++ 空间复杂度$O(\log m + \log n)$ |
| 107 | + |
| 108 | +### AC代码 |
| 109 | + |
| 110 | +#### C++ |
| 111 | + |
| 112 | +```cpp |
| 113 | +/* |
| 114 | + * @Author: LetMeFly |
| 115 | + * @Date: 2024-12-31 13:04:36 |
| 116 | + * @LastEditors: LetMeFly.xyz |
| 117 | + * @LastEditTime: 2024-12-31 13:10:03 |
| 118 | + */ |
| 119 | +#ifdef _WIN32 |
| 120 | +#include "_[1,2]toVector.h" |
| 121 | +#endif |
| 122 | + |
| 123 | +typedef long long ll; |
| 124 | +class Solution { |
| 125 | +public: |
| 126 | + ll minimumCost(int m, int n, vector<int>& horizontalCut, vector<int>& verticalCut) { |
| 127 | + sort(horizontalCut.begin(), horizontalCut.end(), greater<>()); |
| 128 | + sort(verticalCut.begin(), verticalCut.end(), greater<>()); |
| 129 | + int hCutTime = 0, vCutTime = 0; |
| 130 | + ll ans = 0; |
| 131 | + while (hCutTime < horizontalCut.size() || vCutTime < verticalCut.size()) { |
| 132 | + if (vCutTime == verticalCut.size() || hCutTime < horizontalCut.size() && horizontalCut[hCutTime] > verticalCut[vCutTime]) { |
| 133 | + ans += horizontalCut[hCutTime++] * (vCutTime + 1); |
| 134 | + } else { |
| 135 | + ans += verticalCut[vCutTime++] * (hCutTime + 1); |
| 136 | + } |
| 137 | + } |
| 138 | + return ans; |
| 139 | + } |
| 140 | +}; |
| 141 | +``` |
| 142 | +
|
| 143 | +#### Python |
| 144 | +
|
| 145 | +```python |
| 146 | +''' |
| 147 | +Author: LetMeFly |
| 148 | +Date: 2024-12-31 13:10:50 |
| 149 | +LastEditors: LetMeFly.xyz |
| 150 | +LastEditTime: 2024-12-31 13:14:10 |
| 151 | +''' |
| 152 | +from typing import List |
| 153 | +
|
| 154 | +class Solution: |
| 155 | + def minimumCost(self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int]) -> int: |
| 156 | + horizontalCut.sort(key=lambda a: -a) |
| 157 | + verticalCut.sort(key=lambda a: -a) |
| 158 | + ans = hCutTime = vCutTime = 0 |
| 159 | + m, n = m - 1, n - 1 |
| 160 | + while hCutTime < m or vCutTime < n: |
| 161 | + if vCutTime == n or hCutTime < m and horizontalCut[hCutTime] > verticalCut[vCutTime]: |
| 162 | + ans += horizontalCut[hCutTime] * (vCutTime + 1) |
| 163 | + hCutTime += 1 |
| 164 | + else: |
| 165 | + ans += verticalCut[vCutTime] * (hCutTime + 1) |
| 166 | + vCutTime += 1 |
| 167 | + return ans |
| 168 | +``` |
| 169 | + |
| 170 | +#### Java |
| 171 | + |
| 172 | +```java |
| 173 | +/* |
| 174 | + * @Author: LetMeFly |
| 175 | + * @Date: 2024-12-31 13:14:31 |
| 176 | + * @LastEditors: LetMeFly.xyz |
| 177 | + * @LastEditTime: 2024-12-31 13:22:22 |
| 178 | + */ |
| 179 | +import java.util.Arrays; |
| 180 | + |
| 181 | +class Solution { |
| 182 | + public long minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) { |
| 183 | + // Arrays.sort(horizontalCut, (a, b) -> b - a); // 不可,Arrays.sort(int[])时不支持自定义排序 |
| 184 | + Arrays.sort(horizontalCut); // 那就从小到大排序然后下面反着遍历吧 |
| 185 | + Arrays.sort(verticalCut); |
| 186 | + int hCutTime = m - 2, vCutTime = n - 2; |
| 187 | + long ans = 0; |
| 188 | + while (hCutTime >= 0 || vCutTime >= 0) { |
| 189 | + if (vCutTime < 0 || hCutTime >= 0 && horizontalCut[hCutTime] > verticalCut[vCutTime]) { |
| 190 | + ans += horizontalCut[hCutTime--] * (n - vCutTime - 1); |
| 191 | + } else { |
| 192 | + ans += verticalCut[vCutTime--] * (m - hCutTime - 1); |
| 193 | + } |
| 194 | + } |
| 195 | + return ans; |
| 196 | + } |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | +#### Go |
| 201 | + |
| 202 | +```go |
| 203 | +/* |
| 204 | + * @Author: LetMeFly |
| 205 | + * @Date: 2024-12-31 13:23:11 |
| 206 | + * @LastEditors: LetMeFly.xyz |
| 207 | + * @LastEditTime: 2024-12-31 13:37:03 |
| 208 | + */ |
| 209 | +package main |
| 210 | + |
| 211 | +import "slices" |
| 212 | + |
| 213 | +func minimumCost(m int, n int, horizontalCut []int, verticalCut []int) (ans int64) { |
| 214 | + slices.SortFunc(horizontalCut, func(i, j int) int { return j - i; }); |
| 215 | + slices.SortFunc(verticalCut, func(i, j int) int { return j - i; }); |
| 216 | + var hCutTime, vCutTime int |
| 217 | + m, n = m - 1, n - 1 |
| 218 | + for hCutTime < m || vCutTime < n { |
| 219 | + if vCutTime == n || hCutTime < m && horizontalCut[hCutTime] > verticalCut[vCutTime] { |
| 220 | + ans += int64(horizontalCut[hCutTime] * (vCutTime + 1)) |
| 221 | + hCutTime++ |
| 222 | + } else { |
| 223 | + ans += int64(verticalCut[vCutTime] * (hCutTime + 1)) |
| 224 | + vCutTime++ |
| 225 | + } |
| 226 | + } |
| 227 | + return |
| 228 | +} |
| 229 | +``` |
| 230 | + |
| 231 | +> 同步发文于CSDN和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2024/12/31/LeetCode%203219.%E5%88%87%E8%9B%8B%E7%B3%95%E7%9A%84%E6%9C%80%E5%B0%8F%E6%80%BB%E5%BC%80%E9%94%80II/)哦~ |
| 232 | +> |
| 233 | +> Tisfy:[https://letmefly.blog.csdn.net/article/details/144849684](https://letmefly.blog.csdn.net/article/details/144849684) |
0 commit comments