2298 石子合併 2023年省隊選拔賽山東

2021-08-09 08:45:07 字數 1820 閱讀 9770

題目描述 

description

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

試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分。

輸入描述 

input description

第一行是乙個數n。

以下n行每行乙個數a,表示石子數目。

輸出描述 

output description

共乙個數,即n堆石子合併成一堆的最小得分。

樣例輸入 

sample input

樣例輸出 

sample output

資料範圍及提示 

data size & hint

對於 30% 的資料,1≤n≤100

對於 60% 的資料,1≤n≤1000

對於 100% 的資料,1≤n≤40000

對於 100% 的資料,1≤a≤200

思路:1. 這類題目一開始想到是dp, 設dp[i][j]表示第i堆石子到第j堆石子合併最小得分.

狀態方程: dp[i][j] = min(dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);

sum[i]表示第1到第i堆石子總和. 遞迴記憶化搜尋即可.

2. 不過此題有些不一樣, 1<=n<=50000範圍特大, dp[50000][50000]開不到這麼大陣列.

問題分析:

(1). 假設我們只對3堆石子a,b,c進行比較, 先合併哪2堆, 使得得分最小.

score1 = (a+b) + ( (a+b)+c )

score2 = (b+c) + ( (b+c)+a )

再次加上score1 <= score2, 化簡得: a <= c, 可以得出只要a和c的關係確定,

合併的順序也確定.

(2). garsiawachs演算法, 就是基於(1)的結論實現.找出序列中滿足stone[i-1] <=

stone[i+1]最小的i, 合併temp = stone[i]+stone[i-1], 接著往前面找是否

有滿足stone[j] > temp, 把temp值插入stone[j]的後面(陣列的右邊). 迴圈

這個過程一直到只剩下一堆石子結束.

(3). 為什麼要將temp插入stone[j]的後面, 可以理解為(1)的情況

從stone[j+1]到stone[i-2]看成乙個整體 stone[mid],現在stone[j],

stone[mid], temp(stone[i-1]+stone[i-1]), 情況因為temp < stone[j],

因此不管怎樣都是stone[mid]和temp先合併, 所以講temp值插入stone[j]

的後面是不影響結果.

1 #include2 #include3

#define ll long long

4#define maxn 50010

5using

namespace

std;

6int t=1

,n,a[maxn];

7 ll ans=0

;8 inline void read(int&x)

13 inline void go(int

k) 27}28

intmain()

35while(t>1) go(t-1

);36 printf("

%lld\n

",ans);

37return0;

38 }

view code

2298 石子合併

2008年省隊選拔賽山東 時間限制 1 s 空間限制 256000 kb 題目等級 gold 在乙個操場上擺放著一排n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分。輸入描...

SDOI2008 石子合併 題解

題面 garsiawachs演算法專門解決石子合併問題 設乙個序列是a 0.n 1 每次尋找最小的乙個滿足a k 1 a k 1 的k,那麼我們就把a k 與a k 1 合併,並向前尋找乙個第乙個超過他們的和的數,把這個數插入到他後面 include define inc i,a,b for reg...

282 石子合併

設有n堆石子排成一排,其編號為1,2,3,n。每堆石子有一定的質量,可以用乙個整數來描述,現在要將這n堆石子合併成為一堆。每次只能合併相鄰的兩堆,合併的代價為這兩堆石子的質量之和,合併後與這兩堆石子相鄰的石子將和新堆相鄰,合併時由於選擇的順序不同,合併的總代價也不相同。例如有4堆石子分別為 1 3 ...