Luogu P1880 石子合并 题解报告

题目传送门

【题目大意】

在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分。

【思路解析】

首先是断环为链,这题数据不大,没什么问题。

说一下转移方程吧$$f[l][r]=min(f[l][r],f[l][k]+f[k+1][r])+sum[r]-sum[l-1](lle k<r)$$初始值:详见代码

目标:$min(f[i][i+n-1])(iin[1,n]),max(g[i][i+n-1])(iin[1,n])$.

还有就是要注意一下循环嵌套的顺序,哪一个循环在里面,哪一个循环在外面。

【代码实现】

 1 #include<bits/stdc++.h>
 2 #define rg register
 3 #define go(i,a,b) for(rg int i=a;i<=b;i++)
 4 #define back(i,a,b) for(rg int i=a;i>=b;i--)
 5 #define mod 2147483648
 6 #define ll long long
 7 using namespace std;
 8 const int N=102<<1;
 9 int n,a[N],sum[N];
10 ll f[N][N],g[N][N];
11 int main(){
12     scanf("%d",&n);
13     memset(f,0x3f,sizeof(f));memset(g,0,sizeof(g));
14     go(i,1,n) scanf("%d",&a[i]),a[i+n]=a[i];
15     go(i,1,n*2) f[i][i]=0,g[i][i]=0,sum[i]=sum[i-1]+a[i];
16     go(len,2,n) go(l,1,2*n-len+1){
17         int r=l+len-1;
18         go(k,l,r-1){
19             f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
20             g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]);
21         }
22         f[l][r]+=sum[r]-sum[l-1];
23         g[l][r]+=sum[r]-sum[l-1];
24     }
25     ll ans1=123456798,ans2=0;
26     go(i,1,n) ans1=min(ans1,f[i][i+n-1]),ans2=max(ans2,g[i][i+n-1]);
27     printf("%lld
%lld
",ans1,ans2);
28     return 0;
29 }
代码戳这里
原文地址:https://www.cnblogs.com/THWZF/p/10996380.html