1. 程式人生 > >NOI1995石子合併&多種石子合併

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

*****石子合併分為三個梯度的形式
第一種就是一條線那樣的石子合併
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 int i,j,l,k,n,a[105],f[105][105],s[105];
 7 int main()
 8 {
 9     scanf("%d",&n);
10     s[0] = 0;
11     for(i = 1;i <= n;i++)
12 { 13 scanf("%d",&a[i]); 14 s[i] = s[i - 1] + a[i]; 15 } 16 for(l = 2;l <= n;l++) 17 { 18 for(i = 1;i <= n + l - 1;i++) 19 { 20 j = i + l - 1; 21 for(k = i;k <= j - 1;k++) 22 { 23 if(f[i][j] != 0
) 24 f[i][j] = min(f[i][j],f[i][k] + f[k + 1][j] + s[j] - s[i - 1]); 25 else 26 f[i][j] = f[i][k] + f[k + 1][j] + s[j] - s[i - 1]; 27 } 28 } 29 } 30 printf("%d",f[1][n]); 31 return 0; 32 }