3219. 切蛋糕的最小总开销 II
困难题
有一个 m x n 大小的矩形蛋糕,需要切成 1 x 1 的小块。
给你整数 m ,n 和两个数组:
horizontalCut 的大小为 m - 1 ,其中 horizontalCut[i] 表示沿着水平线 i 切蛋糕的开销。
verticalCut 的大小为 n - 1 ,其中 verticalCut[j] 表示沿着垂直线 j 切蛋糕的开销。
一次操作中,你可以选择任意不是 1 x 1 大小的矩形蛋糕并执行以下操作之一:
沿着水平线 i 切开蛋糕,开销为 horizontalCut[i] 。
沿着垂直线 j 切开蛋糕,开销为 verticalCut[j] 。
每次操作后,这块蛋糕都被切成两个独立的小蛋糕。
每次操作的开销都为最开始对应切割线的开销,并且不会改变。
请你返回将蛋糕全部切成 1 x 1 的蛋糕块的 最小 总开销。
题解
自己用递归写的,最后几个测试点超时了。。。。
分析一下leetcode官方的题解吧。
第一段就是引出说可以用贪心的思想,第二段就是证明如果使用贪心的话能达到全局最优解。
使用贪心的方法,每次都沿着开销最大的线切到底。
需要注意的是切到底,切到底就是说把选择的这条线上能切的蛋糕块都切一遍,
例如:先竖切一刀,这时候就分成了两块。如果根据贪心算法,下一刀要在H[i]上横切,要在这条线上把这两块都切了。
题解下面有人问为什么要切到底。其实切到底是选择贪心策略的必然结果。每次都贪心地切一定是切到底的。
第二段就是证明如果使用贪心的算法来切,能得到全局最优解。不会有别的切法比贪心开销更小。(注意前提是使用贪心的切法)。大概就是这么个思路吧,我也说不出花来了()。
最后附上题解的代码
class Solution {
public long minimumCost(int m, int n, int[] horizontalCut, int[] verticalCut) {
Arrays.sort(horizontalCut);
Arrays.sort(verticalCut);
int h = 1, v = 1;
long res = 0;
int horizontalIndex = horizontalCut.length - 1, verticalIndex = verticalCut.length - 1;
while (horizontalIndex >= 0 || verticalIndex >= 0) {
if (verticalIndex < 0 || (horizontalIndex >= 0 && horizontalCut[horizontalIndex] > verticalCut[verticalIndex])) {
res += horizontalCut[horizontalIndex--] * h;
v++;
} else {
res += verticalCut[verticalIndex--] * v;
h++;
}
}
return res;
}
}
作者:力扣官方题解
来源:力扣(LeetCode)