洛谷 1880 石子合併

2022-09-17 18:33:14 字數 1584 閱讀 1081

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

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

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

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

由於本人是大蒟蒻,所以這道題做了好幾個月(其實第一眼看就想到斷環成鏈,但是蒟蒻是完美主義者,所以鐵了心要寫dp)

斷環成鏈的就不說了,點開luogu 題解一大堆.

這裡說一下我的dp思路:

若果是一條鏈,那麼這個問題是很好處理的,有狀態轉移方程(以最小值為例) : f[i][j]=min | i<=k<=j.

那麼成環之後也可以用類似的狀態: 假設石子的序號逆時針遞增,則f[i][j] 表示以逆時針方向的最優合併,那麼f[i][j]|0<=i<=n-1,0<=j<=n-1 就足以表示所有的情況(lrj:想一想,為什麼 ='-') )

蒟蒻覺得用記憶化搜尋比用遞推好(其實是因為遞推的話蒟蒻不知道順序),那麼,請看**:

1//2

3 #include4 #include5

const

int n=100+1,inf=2e9+1;6

inta[n],sum[n],mins[n][n],maxs[n][n],n;

7bool

calmin[n][n],calmax[n][n];

8int min(int a,int b)

9int max(int a,int b)

10 inline int sum(int,int

);11 inline int dp(int,int,int val[n][n],bool vis[n],int(*)(int,int

));12 inline void

init();

13 inline void

dp();

14 inline void

printanswer();

15int

main()

1622 inline int sum(int l,int

r)23

28 inline void

init()

2937

}38 inline void

dp()

39 46}

47 inline int dp(int

from,int to,int val[n],bool vis[n],int (*f)(int,int

))48

60return val[from][to]=ans;61}

62else

if(from==to)

63else

6471

return val[from][to]=ans;72}

73}74 inline void

printanswer()

7582 printf("

%d\n%d

",mina,maxa);

83 }

stoneunion

洛谷1880 石子合併

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

洛谷1880 石子合併

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

洛谷P1880 石子合併

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