dp2 合併石子(一)

2021-09-07 14:10:39 字數 2345 閱讀 8312

一、心得

二、題目

時間限制:

1000 ms  |  記憶體限制:65535 kb

難度:3

描述

有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n-1次合併後成為一堆。求出總的代價最小值。

輸入

有多組測試資料,輸入到檔案結束。

每組測試資料第一行有乙個整數n,表示有n堆石子。

接下來的一行有n(0< n <200)個數,分別表示這n堆石子的數目,用空格隔開

輸出輸出總代價的最小值,佔單獨的一行

樣例輸入

3

1 2 3

713 7 8 16 21 4 18

樣例輸出

9

239

**

經典問題

三、分析

* 合併石子.cpp

* 分析:

* 狀態:

* f[i][j]表示把第i堆石子到第j堆石子合併成一堆的最小代價

* sum[j]表示第1堆石子到第j堆石子的和

* 最終狀態:

* f[1][n]

* 初始狀態:

* f[i][i]=0;

* 狀態轉移方程:

* 假設最後一次合併是將(i,k)和(k+1,j)合併

dp過程圖

四、ac**

242ms

1/*2

* 合併石子.cpp

3* 分析:

4* 狀態:

5* f[i][j]表示把第i堆石子到第j堆石子合併成一堆的最小代價

6* sum[j]表示第1堆石子到第j堆石子的和

7* 最終狀態:

8* f[1][n]

9* 初始狀態:

10* f[i][i]=0;

11* 狀態轉移方程:

12* 假設最後一次合併是將(i,k)和(k+1,j)合併

13* f[i][j]=min(f[i][k]+f[k+1][j]+sum[j]-sum[i-1]) (k>=i&&k<=j)14*

15*16*/

1718 #include 19 #include 20

using

namespace

std;

21int f[205][205

];22

int sum[205

];23

int a[205]; //

用來存這n堆石子

24int

n;25

26void

readdata() 30}

3132

void

printread()

37 cout <

3940

void

initarr_sum() 45}

4647

void

printarr_sum()

51 cout <

5354

void

initarr_f() 60}

61//

初始化62

for (int i = 1; i <= n; i++) 65}

6667

void

printarr_f()

72 cout <

74}7576

void

init()

8485

void

dp() 92}

93}94}

9596

void

printans()

99100

intmain()

108109

return0;

110}

111112

/*113

* 注意點:

114* 1、因為求最小值,所以f要初始化為較大值

115* f[i][j] = 0xfffffff;

116*/

五、注意點

1、因為求最小值,所以f要初始化為較大值

f[i][j] = 0xfffffff;

DP 合併石子

矩陣連乘求最小相乘次數的問題和石子合併的問題思路是一樣的,而二者都是典型的dp 石子合併的問題 問題描述 在一條直線上有n堆石子,每堆有一定的數量,每次可以將兩堆相鄰的石子合併,合併後放在兩堆的中間位置,合併的費用為兩堆石子的總數。求把所有石子合併成一堆的最小花費。輸入格式 輸入第一行包含乙個整數n...

dp 合併石子

靈活的dp啊。靈活的思路啊。怎樣去分析乙個你認為是用簡單dp解決的問題呢。就是把問題盡量想得簡單一點。舉個例子,把大象放進冰箱分為幾步 把大象的頭放進冰箱,把大象的尾巴放進冰箱。都是同樣的 放進冰箱 的操作,涉及的資料的規模變小了,這樣 步驟簡化 就可以有點思路。回到說這道題 你合併這11堆石子,你...

合併石子 dp

時間限制 1 sec 記憶體限制 128 mb 提交 7 解決 7 提交 狀態 討論版 命題人 quanxing 在乙個操場上一排地擺放著 堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的 堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。計算出將 堆石子合併成一堆的最小得分。第...