合并石头的最低成本
有 n 堆石头排成一排,第 i 堆中有 stones[i] 块石头。
每次 移动 需要将 连续的 k 堆石头合并为一堆,而这次移动的成本为这 k 堆中石头的总数。
返回把所有石头合并成一堆的最低成本。如果无法合并成一堆,返回 -1 。
1. 前缀和 + 动态规划
首先分析需要合并(n-k)/(k-1)+1 次
或者说石头个数需要满足(n-k)%(k-1)==0
由于频繁用到一定区间石头数量和,首先使用前缀和预先计算
class Solution {
public:
int mergeStones(vector<int>& stones, int k) {
int n = stones.size();
if(n==1) return 0;
if(n<k) return -1;
if((n-k)%(k-1)!=0) return -1;
//需要合并(n-k)/(k-1)+1 次
//定义dp[i][j][p]把i,j的石头合并成p堆的最小成本
vector<int> presum(n+1);
for(int i=0;i<n;i++)
presum[i+1] = presum[i] + stones[i];
int memo[n][n][k+1];
memset(memo,-1,sizeof(memo));
function<int(int,int,int)> dfs = [&](int i,int j,int p)->int{
if(memo[i][j][p]!=-1) return memo[i][j][p];//剪枝
if(p==1){//合成一堆
if(i==j) return memo[i][j][p]=0;//边界条件1,本来一堆无需合成,成本为0
return memo[i][j][p] = dfs(i,j,k) + presum[j+1]-presum[i];
}
memo[i][j][p] = INT_MAX;
for(int m=i;m<j;m+=k-1)
memo[i][j][p] = min(memo[i][j][p], dfs(i,m,1)+dfs(m+1,j,p-1));
return memo[i][j][p];
};
return dfs(0,n-1,1);
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
2022-05-14 LeetCode/翻转图像
2022-05-14 LeetCode/链表操作综合
2022-05-14 LeetCode/岛屿数量(连通域数量)
2022-05-14 LeetCode/二维矩阵搜索