P1880 [NOI1995]石子合併

題目描述

在一個圓形操場的四周擺放N堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記爲該次合併的得分。

試設計出1個算法,計算出將N堆石子合併成1堆的最小得分和最大得分.

輸入格式

數據的第1行試正整數N,1≤N≤100,表示有N堆石子.第2行有N個數,分別表示每堆石子的個數.

輸出格式

輸出共2行,第1行爲最小得分,第2行爲最大得分.

輸入輸出樣例

輸入 #1複製

4
4 5 9 4

輸出 #1複製

43
54
#include <bits/stdc++.h>
using namespace std;
int s[1000],f1[300][300],f2[300][300],n=0,num[1000];

int d(int i,int j){
    return s[j]-s[i-1];
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n+n;i++){
        if(i<=n)scanf("%d",&num[i]);
        num[i+n]=num[i];
        s[i]=s[i-1]+num[i];
    }
    for(int p=1;p<n;p++)
        for(int i=1,j=i+p;(i<n*2)&&(j<n*2);i++,j=i+p){
            f2[i][j]=65536;
            for(int k=i;k<j;k++){
                f1[i][j]=max(f1[i][j],f1[i][k]+f1[k+1][j]+d(i,j));
                f2[i][j]=min(f2[i][j],f2[i][k]+f2[k+1][j]+d(i,j));
            }
        }
    int minv=65536,maxv=0;
    for(int i=1;i<=n;i++){
        maxv=max(maxv,f1[i][i+n-1]);
        minv=min(minv,f2[i][i+n-1]);
    }
    cout<<minv<<endl<<maxv;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章