在乙個圓形操場的四周擺放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個數,分別表示每堆石...