石子合并问题

在一个圆形操场的四周摆放 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 }
石子合并问题

 

posted @ 2025-04-06 16:40  TP_003  阅读(37)  评论(0)    收藏  举报