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;
}

猜你喜欢

转载自www.cnblogs.com/yzm10/p/9703195.html