执行结果:通过

题目 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
的蛋糕块的 最小 总开销。
示例 1:
**输入:**m = 3, n = 2, horizontalCut = [1,3], verticalCut = [5]
**输出:**13
解释:

- 沿着垂直线 0 切开蛋糕,开销为 5 。
- 沿着水平线 0 切开
3 x 1
的蛋糕块,开销为 1 。 - 沿着水平线 0 切开
3 x 1
的蛋糕块,开销为 1 。 - 沿着水平线 1 切开
2 x 1
的蛋糕块,开销为 3 。 - 沿着水平线 1 切开
2 x 1
的蛋糕块,开销为 3 。
总开销为 5 + 1 + 1 + 3 + 3 = 13
。
示例 2:
**输入:**m = 2, n = 2, horizontalCut = [7], verticalCut = [4]
**输出:**15
解释:
- 沿着水平线 0 切开蛋糕,开销为 7 。
- 沿着垂直线 0 切开
1 x 2
的蛋糕块,开销为 4 。 - 沿着垂直线 0 切开
1 x 2
的蛋糕块,开销为 4 。
总开销为 7 + 4 + 4 = 15
。
提示:
1 <= m, n <= 105
horizontalCut.length == m - 1
verticalCut.length == n - 1
1 <= horizontalCut[i], verticalCut[i] <= 103
代码以及解题思路
代码:
int compare(const void* a, const void* b) {
return (*(int*)b - *(int*)a);
}
long long minimumCost(int m, int n, int* horizontalCut, int horizontalCutSize, int* verticalCut, int verticalCutSize) {
qsort(horizontalCut, horizontalCutSize, sizeof(int), compare);
qsort(verticalCut, verticalCutSize, sizeof(int), compare);
long long h = 1, v = 1;
long long res = 0;
int hIndex = 0, vIndex = 0;
while (hIndex < horizontalCutSize || vIndex < verticalCutSize) {
if (vIndex == verticalCutSize || (hIndex < horizontalCutSize && horizontalCut[hIndex] > verticalCut[vIndex])) {
res += horizontalCut[hIndex++] * h;
v++;
} else {
res += verticalCut[vIndex++] * v;
h++;
}
}
return res;
}
解题思路:
- 排序切割线 :
- 使用
qsort
函数对horizontalCut
和verticalCut
数组进行排序。compare
函数确保了排序是按照降序进行的,这对于后续步骤中的比较和计算至关重要。排序的目的是为了方便处理切割线,确保在计算成本时,我们可以按顺序处理水平切割线和垂直切割线。
- 使用
- 初始化变量 :
h
和v
分别表示当前处理到的水平区域的高度和垂直区域的宽度。初始时,整个蛋糕是一个完整的区域,所以高度和宽度均为1。res
用于累加总的切割成本。hIndex
和vIndex
分别表示当前处理的水平切割线和垂直切割线的索引。
- 遍历切割线 :
- 使用
while
循环遍历所有的切割线。循环条件是hIndex < horizontalCutSize || vIndex < verticalCutSize
,意味着只要还有未处理的切割线,就继续循环。 - 在循环内部,通过比较当前处理的水平切割线和垂直切割线的位置,决定先处理哪一条切割线。由于切割线数组是降序排序的,所以可以直接通过比较当前索引对应的切割线位置来决定。
- 如果先处理水平切割线,那么将该切割线对应的面积(
horizontalCut[hIndex] * h
)加到总成本res
上,并将水平区域的计数h
加1,表示现在处理的是下一个水平区域。同时,水平切割线索引hIndex
自增。 - 如果先处理垂直切割线,那么操作类似,只不过是将垂直区域的宽度
v
加1,并更新垂直切割线索引vIndex
。
- 使用
- 返回结果 :
- 当所有的切割线都被处理后,循环结束,返回累加的总成本
res
。
- 当所有的切割线都被处理后,循环结束,返回累加的总成本
总结:
- 代码通过排序确保切割线按顺序处理。
- 使用两个变量
h
和v
分别追踪当前处理的水平区域的高度和垂直区域的宽度。 - 通过比较当前处理的切割线位置,决定先处理哪一条切割线,并计算相应的成本。
- 最终返回所有切割操作所需的最小成本。