BZOJ3229 石子合併

2021-09-25 04:20:16 字數 1874 閱讀 9937

description

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

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

input

第一行是乙個數n。

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

output

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

sample input41

111sample output

8hint

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

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

題解:一般的石子合併在dp+四邊形優化後複雜度為o(n

2n^2

n2),這題資料範圍顯然不行。

所以此題正解為garsiawachs演算法

下面簡述一下該演算法的流程以及結論:

(為了方便起見,我們規定a[0] = a[n+1] = inf)

①從序列的左端開始找第乙個滿足a[k−1]a[k+1]的 k,然後合併a[k−1]a[k]

②從當前合併位置向左尋找第乙個滿足a[j]>a[k-1] + a[k]j,然後將合併後的值插在a[j]

③重複上述過程(n-1次),直到只剩下一堆,總合併代價即為①中每次合併代價之和

演算法複雜度為o(nlogn)

該定理保證,如此操作後答案不會改變

acode:

//o(nlogn)

#include

#include

typedef

long

long ll;

using

namespace std;

const

int mx =

4e4+7;

const

int inf =

0x3f3f3f3f

;int n,m,ans,a[mx]

;int

main

(int argc,

char

const

*ar**)

}//將a[k-1] 和 a[k] 合併

a[k-1]

+= a[k]

;for

(int j = k;j < m;

++j)

a[j]

= a[j +1]

; ans +

= a[

--k]

;//從k向左找第乙個a[j] > a[k - 1] + a[k] 的 j,把合併後的值插在a[j]後面

while

(k >

0&& a[k-1]

<= a[k]

) a[m]

= inf;

m--;}

cout << ans << endl;

return0;

}

regina8023

lwq12138

石子合併 BZOJ 3229

題目傳送門 題意 石子合併問題一般來說都是o n 3 的複雜度,如果用四邊形不等式優化的話可以使時間複雜度降低到o n 2 的複雜度,但是這個題目的資料範圍是40000,所以這個題要用到garsiawachs演算法,可以使時間複雜度降到o n logn 從而解決這個題目。include includ...

BZOJ 3229 Sdoi2008 石子合併

時間限制 3 sec 記憶體限制 128 mb 提交 497 解決 240 提交 在乙個操場上擺放著一排n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分。第一行是乙個數n。...

282 石子合併

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