HRBUST - 1819 石子合并问题--圆形版(区间dp+环形+四边形优化)
石子合并问题--圆形版
在圆形操场上摆放着一行共n堆的石子。现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请编辑计算出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。
Input
输入有多组测试数据。
每组第一行为n(n<=100),表示有n堆石子,。
二行为n个用空格隔开的整数,依次表示这n堆石子的石子数量ai(0<ai<=100)
Output
每组测试数据输出有一行。输出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。 中间用空格分开。
Sample Input
3
1 2 3
Sample Output
9 11
#include<bits/stdc++.h> #define MAX 205 #define INF 0x3f3f3f3f using namespace std; typedef long long ll; int a[MAX],sum[MAX]; int dp1[MAX][MAX],dp2[MAX][MAX]; int s[MAX][MAX]; int main() { int n,len,i,j,k; while(~scanf("%d",&n)){ memset(dp1,INF,sizeof(dp1)); memset(dp2,0,sizeof(dp2)); memset(s,0,sizeof(s)); memset(sum,0,sizeof(sum)); for(i=1;i<=n;i++){ scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; dp1[i][i]=0; s[i][i]=i; } for(i=n+1;i<2*n;i++){ //环形处理 sum[i]=sum[i-1]+a[i-n]; dp1[i][i]=0; s[i][i]=i; } for(len=2;len<=n;len++){ for(i=1;i<2*n-1;i++){ j=i+len-1; if(j>2*n-1) break; for(k=s[i][j-1];k<=s[i+1][j];k++){ //四边形优化求最小 if(dp1[i][j]>dp1[i][k]+dp1[k+1][j]+sum[j]-sum[i-1]){ dp1[i][j]=dp1[i][k]+dp1[k+1][j]+sum[j]-sum[i-1]; s[i][j]=k; } } for(k=i;k<j;k++){ if(dp2[i][j]<dp2[i][k]+dp2[k+1][j]+sum[j]-sum[i-1]){ dp2[i][j]=dp2[i][k]+dp2[k+1][j]+sum[j]-sum[i-1]; } } } } int minn=INF,maxx=0; for(i=1;i<=n;i++){ minn=min(minn,dp1[i][i+n-1]); maxx=max(maxx,dp2[i][i+n-1]); } printf("%d %d\n",minn,maxx); } return 0; }
博文系博主原创,转载请注明出处 o(* ̄▽ ̄*)ブ 更多博文源自https://www.cnblogs.com/yzm10