石子合并问题
在一个圆形操场的四周摆放 N 堆石子,现要将石子有次序地合并成一堆,
规定每次只能选相邻的 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出一个算法,计算出将 N 堆石子合并成 1 堆的最小得分和最大得分。
洛谷题号:P1880 https://www.luogu.com.cn/problem/P1880
状态转移方程
dp[i][j]:表示将第i~j对石子合并为一堆石子的最小得分
dp[i][j]= min( dp[i][k] + dp[k+1][j] ) (i <= k < j)
k是某个分界点,左边一堆 i~k 的最小得分就是dp[i][k],右边一堆 k+1~j 的最小得分是dp[k+1][j]
状态转移方程需要结合分析图来看,分析图参考同目录下的 '11 石子合并问题.png'
这里先用递归方式来实现上述动态转移方程
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int a[100]; 5 int dp[100][100]; 6 int n; 7 int stoneMerge(int l,int r){ 8 if(l==r){ 9 return 0; 10 } 11 if(dp[l][r]>0){ 12 return dp[l][r]; 13 } 14 int ans=INT_MAX; 15 for(int k=l;k<r;k++){ 16 ans=min(ans,stoneMerge(l,k)+stoneMerge(k+1,r)); 17 } 18 ans+=(a[r]-a[l-1]); 19 dp[l][r]=ans; 20 return dp[l][r]; 21 } 22 int main(){ 23 cin>>n; 24 for(int i=1;i<=n;i++){ 25 cin>>a[i]; 26 a[i]+=a[i-1]; 27 } 28 int minScore=stoneMerge(1,n); 29 cout<<minScore; 30 return 0; 31 }

浙公网安备 33010602011771号