SSLOJ1597 P1880 石子合併

2021-10-23 12:12:43 字數 2259 閱讀 7494

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

程式設計任務:

對於給定n堆石子,程式設計計算合併成一堆的最小得分和最大得分。

輸入包括多組測試資料,每組測試資料報括兩行。

第1 行是正整數n,1<=n<=100,表示有n堆石子。

第2行有n個數,分別表示每堆石子的個數。

對於每組輸入資料,輸出兩行。

第1 行中的數是最小得分;第2 行中的數是最大得分。

44 4 5 9

4354

一道明顯的dp

f[i][j]為合併從i到j的最小代價,f2[i][j]為合併從i到j的最大代價

方程:f[i

][j]

=max

(f[i

][k]

+f[k

+1][

j]+s

[j]−

s[i−

1])(

i<=k

f[i][j]=max(f[i][k]+f[k+1][j]+s[j]-s[i-1])(i<=kf[

i][j

]=ma

x(f[

i][k

]+f[

k+1]

[j]+

s[j]

−s[i

−1])

(i<=k

f [i

][j]

=min

(f[i

][k]

+f[k

+1][

j]+s

[j]−

s[i−

1])(

i<=k

f[i][j]=min(f[i][k]+f[k+1][j]+s[j]-s[i-1])(i<=kf[

i][j

]=mi

n(f[

i][k

]+f[

k+1]

[j]+

s[j]

−s[i

−1])

(i<=k

s[i]為從i至1的和

上**:

#include

#include

using

namespace std;

int n,a[

300]

,s[300

],dp[

300]

[300][

2];int

main()

for(

int i=

1;i<=

2*n;i++

) s[i]

=s[i-1]

+a[i]

;for

(int l=

1;l)for

(int i=

1,j=i+l;j<

2*n&&i<

2*n;i++

,j=i+l)

}int mx=

0,mn=

0x7f7f7f7f

;for

(int i=

1;i<=n;i++

) cout

}

另一種**:

#include

#include

using

namespace std;

int n,a[

300]

,s[300

],dp[

300]

[300][

2];int

main()

int mx2=

0,mn2=

0x7f7f7f7f

;for

(int i2=

1;i2<=n;i2++)}

int mx=

0,mn=

0x7f7f7f7f

; mx=

max(dp[1]

[n][0]

,mx)

; mn=

min(dp[1]

[n][1]

,mn)

; mn2=

min(mn2,mn)

; mx2=

max(mx,mx2);}

cout

}

還有第3種:

見我的新部落格

p1880 石子合併

先從線性的開始吧。有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。樣例 輸入 3 1 2 3 7 13 7 8 16 21 4 18 輸出 9 239 ...

P1880 石子合併

石子歸併最簡單的情況是一排石子,典型的區間dp問題。dp i j 的含義是區間 i,j 合併之後的最大或最小花費 轉移方程 dp i j max min dp i j dp i k dp k 1 j val i,j 對於區間 i,j 它可以由區間 i,k 和區間 k 1,j 合併而來,合併時,要加上...

P1880石子合併

傳送 這是乙個年代久遠的區間dp 好像以前培訓的時候講了,但是現在才想起來去a 區間dp常用狀態 f i j 以i為左端點,j為右端點的最優解 第一層迴圈列舉區間長度,第二層迴圈列舉起點,第三層列舉中間的斷點 貌似寫到這裡這個題就寫完了 特點 問題能轉換為兩兩合併的問題 such as 能量項鍊,石...