HRBUST 1819

石子合并问题--圆形版
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 61(27 users) Total Accepted: 26(22 users) Rating:  Special Judge: No
Description
在圆形操场上摆放着一行共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

代码:

//前一个题的变形,直线变环,把石子接成2*n堆,再进行dp就行了,始终控制区间的最大长度是n。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
int n,a[210],dp1[210][210],dp2[210][210],sum[210];
int main()
{
    while(scanf("%d",&n)==1){
        sum[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a[n+i]=a[i];
        }
        memset(dp1,inf,sizeof(dp1));
        memset(dp2,0,sizeof(dp2));
        for(int i=1;i<=2*n;i++){
            sum[i]=sum[i-1]+a[i];
            dp1[i][i]=dp2[i][i]=0;
        }
        for(int i=2;i<=2*n;i++){
            for(int j=i-1;j>=(i<=n?1:i-n+1);j--){
                for(int k=j;k<i;k++){
                    dp1[j][i]=min(dp1[j][i],dp1[j][k]+dp1[k+1][i]+sum[i]-sum[j-1]);
                    dp2[j][i]=max(dp2[j][i],dp2[j][k]+dp2[k+1][i]+sum[i]-sum[j-1]);
                }
            }
        }
        int ans1=inf,ans2=0;
        for(int i=1;i<=n;i++){
            ans1=min(ans1,dp1[i][i+n-1]);
            ans2=max(ans2,dp2[i][i+n-1]);
        }
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}

 

posted @ 2017-04-24 18:21  luckilzy  阅读(406)  评论(0编辑  收藏  举报