石子合併 (區間DP)

2021-09-26 07:56:01 字數 996 閱讀 5211

題目鏈結

描述    

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

輸入第一行有乙個整數n,表示有n堆石子。

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

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

樣例輸入

3

1 2 3

樣例輸出

9
首先從集合的角度考慮狀態,用 f [i, j] 應該表示的是怎樣乙個狀態,因為最後要合併的是全部的石子,合併石子的方案有很多,我們可以用 f [i, j] 表示第 i 到 j 區間內的石子合併的全部方案,用 f [i, j] 的值表示所有方案中的最小代價,因此初始化時應該把 f 陣列初始化為極大值,考慮狀態轉移,f [i, j] 一定可以由 i 到 j 中間乙個點分開,分成兩堆,再次合併,因此假設從 k 這個點分成兩半,即有 f [i, j] = min(f [i, k - 1] + f[k, j] + 兩堆石子合併的代價),兩堆石子合併的代價就是區間 i 到 j 內的和,可以用字首和的方式快速求解,方程雖然這樣寫,但是並不能以直接列舉區間的起點和終點,因為我們要保證在計算當前狀態時,所需要的狀態都被計算過了,可以列舉區間長度,從小到大,在計算大長度區間時所需要的小長度一定被計算過了,然後列舉起點,最後列舉中間的斷點 k 即可

#include #include #include #include using namespace std;

const int n = 310;

int a[n], f[n][n], sum[n];

int n;

int main()

} }printf("%d\n", f[1][n]);

return 0;

}

石子合併 (區間DP

問題描述 在乙個操場上擺放著一行共n堆的石子。現要將石子有序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆石子數記為該次合併的得分。請編輯計算出將n堆石子合併成一堆的最小得分和將n堆石子合併成一堆的最大得分。輸入檔案 輸入第一行為n n 1000 表示有n堆石子,第二行為n個用空...

石子合併 區間dp

有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。假設dp 1 4 表示將區間1 4的石子合併所花費的代價。dp 1 4 可以劃分為dp 1 1 dp 2...

區間DP 石子合併

區間dp的經典例題,有三種題型 本篇部落格借鑑了了兩位大佬的部落格。部落格1 部落格2 問題 n堆石子,現要將石子有序的合併成一堆。每次只能移動任意的2堆石子合併,合併花費為新合成的一堆石子的數量。求將這n堆石子合併成一堆的總花費最小 或最大 思路 貪心,每次把最小的兩堆合併即可,可以使用stl中的...