在C ++中合并石头的最低成本
假设我们有N排石头排成一排。在这里,第i堆有石头[i]数。一次移动包括将K个连续的桩合并为一个桩,现在此移动的成本等于这K个桩中的石头总数。我们必须找到将所有石头堆成一堆的最低成本。如果没有这样的解决方案,则返回-1。
因此,如果输入像[3,2,4,1]且K=2,则输出将为20,这是因为我们将从[3,2,4,1]开始。然后我们以成本5合并[3,2],剩下[5,4,1]。之后,我们以5的成本合并[4,1],然后剩下[5,5]。然后我们以成本10合并[5,5],剩下[10]。因此,总成本为20,这是最低的成本。
为了解决这个问题,我们将遵循以下步骤-
n:=石头大小
如果(n-1)mod(k-1)不等于0,则-
返回-1
定义大小为n+1的数组前缀
对于初始化i:=1,当i<=n时,更新(将i增加1),-
prefix[i]:=前缀[i-1]+石头[i-1]
定义一个大小为nxn的2D数组dp
对于初始化长度:=k,当长度<=n时,更新(将长度增加1),-
dp[i,j]:=dp[i,j]+前缀[j+1]-前缀[i]
dp[i,j]:=dp[i,j]和dp[i,mid]的最小值+dp[mid+1,j]
对于初始化i:=0,j:=长度-1,当j<n时,更新(i增加1),(j增加1),-
dp[i,j]:=inf
对于初始化mid:=i,当mid<j时,更新mid:=mid+k-1,执行-
如果(j-i)mod(k-1)等于0,则-
返回dp[0,n-1]
让我们看下面的实现以更好地理解-
示例
#include <bits/stdc++.h> using namespace std; class Solution { public: int mergeStones(vector<int>& stones, int k){ int n = stones.size(); if ((n - 1) % (k - 1) != 0) return -1; vector<int> prefix(n + 1); for (int i = 1; i <= n; i++) { prefix[i] = prefix[i - 1] + stones[i - 1]; } vector<vector<int>> dp(n, vector<int>(n)); for (int length = k; length <= n; length++) { for (int i = 0, j = length - 1; j < n; i++, j++) { dp[i][j] = INT_MAX; for (int mid = i; mid < j; mid += k - 1) { dp[i][j] = min(dp[i][j], dp[i][mid] + dp[mid + 1][j]); } if ((j - i) % (k - 1) == 0) { dp[i][j] += prefix[j + 1] - prefix[i]; } } } return dp[0][n - 1]; } }; main(){ Solution ob; vector<int> v = {3,2,4,1}; cout << (ob.mergeStones(v, 2)); }
输入值
{3,2,4,1}, 2
输出结果
20