P1880 NOI1995 石子合併

2021-09-25 04:49:07 字數 1338 閱讀 3319

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

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

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

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

4

4 5 9 4

輸出樣例#1:
43

54

設dp[ i ] [ j ]為區間 [ i , j ]內 j - i + 1個 小堆堆成乙個大堆的總分的最小/最大值。

則 dp [ i ] [ j ] =兩子區間:dp[i][k]、dp[k+1][j]得分之和加上 兩個子區間石子的總和,可以用字首和求的。

#include.h>

using namespace std;

char buf[

100000],

*l=buf,*r

=buf;

#define gc()

l==r&&

(r=(

l=buf)

+fread

(buf,1,

100000

,stdin),l

==r)?

eof:*l

++;template>

inline void

read(t

&x)int a[

220]

,sum[

220]

,n,dp_min[

220]

[220

],dp_max[

220]

[220];

int main()

for(int i=

1; i<=

2*n;

++i)

for(int l=

2; l<=n;

++l)

dp_min[i]

[j]+=sum[j]

-sum[i-1]

;//再加上該次合成的得分,即為區間[i,j]的最終得分。

dp_max[i]

[j]+=sum[j]

-sum[i-1]

;}} int ans_min=

0x3f3f3f3f

,ans_max=

-0x3f3f3f3f

;for

(int i=

1; i<=n;

++i)

cout

}

P1880 NOI1995 石子合併

在乙個圓形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分.資料的第1行試正整數n,1 n 100,表示有n堆石子.第2行有n個數,分別表示每堆石...

P1880 NOI1995 石子合併

這次還是給大家講解一下dp 我們則需要根據這個題目的實際含義進行變通即可.而區間dp的大致模板是 for int len 2 len n len for int i 1 i len 1 n i 那講到這裡就很自然 一點都不自然 的引入了今天我們要看的一道題,剛才我已經說了最長不下降子串行是線性dp的...

P1880 NOI1995 石子合併

在乙個圓形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分.資料的第1行試正整數n,1 n 100,表示有n堆石子.第2行有n個數,分別表示每堆石...