動態規劃之合併石子

2021-10-09 01:43:01 字數 2068 閱讀 2699

首先我們要搞懂什麼是動態規劃。我覺得動態規劃就是把乙個大問題分解為多個小問題,每個小問題的決策都會影響到下乙個小問題的決策。(下乙個小問題的決策就是由上乙個小問題的決策而產生的。)乙個狀態經過乙個決策變成了另外乙個狀態,這個過程就是狀態轉移,用來描述狀態轉移的方程就是狀態轉移方程。

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

我們首先來分析乙個比較簡單的問題,現在一共有三堆石頭,每堆石子的數量分別是3,4,11。求合併成一堆石頭的最小得分。

對於這個問題,只有兩種選擇:

前兩堆石頭合併再和第三堆石頭合併。

3+4=7 ——> 7 石堆變為(7, 11)

7+11=18——>18 石堆變為(18)

cost=7+18=25

後兩堆石頭合併再和第一堆石頭合併。

4+11=15——>15 石堆變為(3,15)

3+15=18——>18 石堆變為(18)

cost=15+18=33

易看出先合併前兩堆的石子的花費比較小,不同的合併方式會造成不同的得分。同時可以發現這兩種方法最後一次的得分就是石頭的總數。

現在我們用乙個陣列arr按順序儲存每個位置的石頭數量。

arr=

二維陣列sum[i][j]表示第i堆石頭到第j堆石頭的總和

sum[0][1]=3+4=7;

sum[1][2]=4+11=15;

sum[0][2]=3+4+11=18;

最後用乙個二維陣列dp[i][j]表示從第i堆到第j堆石頭合併的最小分數。

1)每堆石頭跟自己合併的分數都是0。

dp[0][0]=dp[1][1]=dp[2][2]=0

2)相鄰兩堆石頭的最小合併分數只有一種可能。

dp[0][1]=3+4=7, dp[1][2]=4+11=15

3)剩下的就是不相鄰石頭的合併最小花費。

設乙個k∈[i,j];

dp[i][j]=dp[i][k]+dp[k][j]+sum[i][j];

那麼從i到j的所有花費都可以表示出來了,取乙個使得dp[i][j]最小的值。

我們用**來表示出從i到j的費用最小值。(對於c來說一般是序號從0開始)

dp[1][3]=min(dp[1][1]+dp[2][3] , dp[1][2]+dp[3][3])+sum[1][3];

dp[2][4]=min(dp[2][3]+dp[4][4] , dp[2][2]+dp[3][4])+sum[2][4];

dp[1][4]=min(dp[1][1]+dp[2][4],dp[1][2]+dp[3][4],dp[1][3]+dp[4][4])+sum[1][4];

我們最終的目的是求出dp[1][4],那我們就要先求出dp[1][3]和dp[2][4],從影象上我們要求最右上角的值,就是沿著副對角線一步步往上求。

思路就是這樣了,下面是**。

#include

intmain()

for(i=

0; i

)else

sum[i]

[j]=sum[i]

[j-1

]+arr[j];}

}//計算從i到j的石頭總和

for(i=

0; i

//把同一堆石頭和相鄰兩堆石頭合併的值計算

for(t=

2; t<=n; t++)}

if(a<=b)

else

dp[i]

[i+t]

=b;}

}//按照**從副對角線往依次計算的方法,最後求出右上角的值

printf

("%d"

,dp[0]

[n-1])

;return0;

}

有更好的方法歡迎交流~~

想學動態規劃的可以看看這篇文章:告別動態規劃,連刷40道動規演算法題,我總結了動規的套路。

動態規劃專題之石子合併

動態規劃專題講義 專題九 合併石子問題 name 動態規劃專題之石子合併 author 巧若拙 description 在乙個操場上擺放著一排n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。試設計乙個演算法,計算出將n堆石子合...

動態規劃 石子合併

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

石子合併動態規劃

在乙個園形操場的四周擺放n堆石子 n 100 現要將石子有次序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。編一程式,由檔案讀入堆數n及每堆的石子數 20 選擇一種合併石子的方案,使得做n 1次合併,得分的總和最小 選擇一種合併石子的方案,使得做n ...