NOI1995 石子合併

2022-07-22 06:03:11 字數 2181 閱讀 9681

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

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

輸入格式:

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

輸出格式:

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

輸入樣例#1:

6

2 3 4 6 5 4

輸出樣例#1:

61

91題目解析

第一次做這種題型的大佬們應該不會把它當成貪心來做吧???反正小蒟蒻我是做錯了啦!!!

後面有分析了幾個手推資料,發現!!! 這是一題動規,還是一題區間動規!!!

讓我們先看看樣例:

這是最小值的求法,看起來好像和貪心很像勒!!!但其實只是樣例資料給出的假象罷了!!!

很多的大佬和蒟蒻

做題時用了貪心結果只有30分!!!

首先如何解決上圖環的問題呢???

當然很簡單啦,我們把它存成一條鏈:即把t存成2*t

如:2 3 4 6 5 42 3 4 6 5 4 這樣每次列舉i到i+n-1就可以了是吧是不是很簡單啊(^▽^ ) (i<=n)

上文我們說到這是一題動規,那麼我們來分析一下:

1.根據題意可知每次都是兩堆石子合併成一堆,並且這兩堆石子是相鄰的!!

那麼這兩堆石子又是由另外的石子合併的,那麼我們可以認為i到j堆石子是由f[i][k]和f[k+1][j]合成的。那麼

f[i][k]也是根據上面的規則求得到!!!

2.那麼合成的分數如何表示的呢???( -'`-)

已知每個點的分數都是確定的,那麼無論前面的資料如何合併的分數一定是由前面sum[j]-sum[i-1]的值,sum[i]=sum[i-1]+t[i];,

因此得到f[i][j]=max(f[i][k]+[k+1][j]+sum[j]-sum[i-1],f[i][j]);

至此這題大水題已經解決了剩下的只是要考慮合併幾次的問題而已

因為第一次至少兩堆合併,那麼就有了l (l=2;l<=n;++l)

j=i+l-1;

最後就是求一下答案列舉一遍就行了!!

下面正解**:

1 #include2 #include3 #include4 #include5

using

namespace

std;

6const

int maxn=0xfffff,minn=0

;7 inline int read()//快讀8

15while

(isdigit(ch))

1619

return w?-x:x;20}

21int t[210],f1[210][210],f2[210][210],sum[210];//

t為輸入的石子堆,f1為第一問的答案求解,f2為第二問的答案求解,sum為求前i堆石子的合總值

22int main(void)23

39 f1[i][j]+=(sum[j]-sum[i-1]);//

加上此次合併值

40 f2[i][j]+=(sum[j]-sum[i-1

]);41}42

}43int ans1=maxn,ans2=minn;

44for(int i=1; i<=n; ++i)

4549 printf("

%d\n%d

",ans1,ans2);//

輸出50

return0;

51 }

[noi1995] 石子合併

NOI1995 石子合併

在乙個園形操場的四周擺放n堆石子,現要將石子有次序地合併成一堆.規定每次只能選相鄰的2堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。試設計出1個演算法,計算出將n堆石子合併成1堆的最小得分和最大得分.圓的話就用2 n 1,即只有n種情況 include using namespace ...

NOI 1995 石子合併

合併石子的加強版 不過這可是95年的noi的題,準確說應該是合併石子是它的削弱版吧。環的處理就是在鏈的後面再來一遍鏈,然後列舉一下起點終點,就和合併石子一樣了。include include include include include define inf 0x3f3f3f3f using na...

NOI1995 石子合併

本來以為是一道簡單的區間dp問題,草草地寫了個程式結果樣例都沒過,仔細一看,原來n堆石子擺成了環。區間dp是線性dp的一種,寫法比較固定,一般是先列舉區間長度,再列舉區間左端點,推出區間右端點,狀態轉移通常是列舉中間點。這道題雖然成了環,但本質是不變的,還是從2到n列舉區間長度,只不過區間左端點可以...