2023-04-04每日一题
一、题目编号
1000. 合并石头的最低成本
二、题目链接
https://leetcode.cn/problems/minimum-cost-to-merge-stones/
三、题目描述
有 N 堆石头排成一排,第 i 堆中有 stones[i] 块石头。
每次移动(move)需要将连续的 K 堆石头合并为一堆,而这个移动的成本为这 K 堆石头的总数。
找出把所有石头合并成一堆的最低成本。如果不可能,返回 -1 。
四、解题代码
class Solution {
const int inf = 10000000;
public:
int mergeStones(vector<int>& stones, int k) {
int n = stones.size();
if( ( n - 1) % ( k - 1 ) != 0){//将k堆合并成1堆要减少k-1堆,所以n-1必须是k-1的倍数才能够满足
return -1;
}
vector dp(n, vector(n, vector<int>((k+1), inf)));
vector<int> sum(n, 0);
for(int i = 0; i < n; ++i){
dp[i][i][1] = 0;
if(i == 0){
sum[i] = stones[i];
continue;
}
sum[i] = (sum[i-1] + stones[i]);
}
for(int len = 2; len <= n; ++len){
for(int l = 0; l + len - 1 < n; ++l){
int r = l + len - 1;
for(int s = 2; s <= k; ++s){
for(int mid = l; mid < r; mid += (k-1)){
dp[l][r][s] = min(dp[l][r][s], dp[l][mid][1] + dp[mid+1][r][s-1]);
}
}
dp[l][r][1] = min(dp[l][r][1], dp[l][r][k] + sum[r] - ((l == 0) ? 0 : sum[l-1]));
}
}
return dp[0][n-1][1];
}
};
五、解题思路
(1)如果k为2的话就是最基础的区间dp,但是k不为2,所以需要第三个维度来表示合成s堆所需要的代价。
(2)如果n-1不为k-1的倍数的话,则一定是无法实现的。初始化将除了dp
(3)一层循环用来遍历区间范围,二层循环用来遍历左端点,则用端点可以表示为l + len - 1.三层循环用来遍历第三个维度,即将l到r分为多少堆。四层循环用来遍历左到有区间之间的端点。从左到右,跨度是k-1,因为k个合并成1个。
(4)根据状态转移方程进行转化。