CH5301 石子合併 區間dp

2022-06-26 03:57:11 字數 1556 閱讀 2755

描述

設有n堆沙子排成一排,其編號為1,2,3,…,n(n<=300)。每堆沙子有一定的數量,可以用乙個整數來描述,現在要將這n堆沙子合併成為一堆,每次只能合併相鄰的兩堆,合併的代價為這兩堆沙子的數量之和,合併後與這兩堆沙子相鄰的沙子將和新堆相鄰,合併時由於選擇的順序不同,合併的總代價也不相同,如有4堆沙子分別為 1  3  5  2 我們可以先合併1、2堆,代價為4,得到4 5 2 又合併 1,2堆,代價為9,得到9 2 ,再合併得到11,總代價為4+9+11=24,如果第二步是先合併2,3堆,則代價為7,得到4 7,最後一次合併代價為11,總代價為4+7+11=22;問題是:找出一種合理的方法,使總的代價最小。輸出最小代價。

輸入格式

第一行乙個數n表示沙子的堆數n。

第二行n個數,表示每堆沙子的質量(<=1000)。

輸出格式

合併的最小代價

樣例輸入

4

1 3 5 2

樣例輸出
22
**

ccf noi1995

題意:n堆石子,每堆有乙個重量ai。現在想把他們合併成一堆,每次只能合併相鄰的。花費的體力是合併的兩堆石子重量和。要求花費體力最小。

思路:任意時刻,任意一堆石子可以用乙個閉區間[l,r]來描述,表示這堆石子是有最初的第l~r堆石子合併成的。一定存在乙個整數k,在這堆石子形成前,先有l~k堆石子被合併,k+1~r堆石子被合併,然後這兩堆才合併為l~r

兩個長度較小的區間上的資訊向乙個更長的區間發生了轉移,劃分點k就是轉移的決策。把區間長度len作為dp的階段。

虐狗寶典筆記:

區間dp以「區間長度」作為dp的階段,使用兩個座標(區間的左右端點)描述每個維度。區間dp中,乙個狀態由若干個比它更小且包含於它的區間所帶代表的狀態轉移而來,因此區間dp的決策往往就是劃分區間的方法。

實現動態規劃的狀態轉移方程時,務必分清階段、狀態與決策,三者應該按照從外到內的順序依次迴圈。

1

//#include

2 #include3 #include4 #include5 #include6 #include7 #include8

9#define inf 0x3f3f3f3f

10using

namespace

std;

11 typedef long

long

ll;12

13int

n;14

const

int maxn = 305;15

inta[maxn];

16int

dp[maxn][maxn], sum[maxn];

1718

intmain()

1928

29for(int len = 2; len <= n; len++)

35 dp[l][r] += sum[r] - sum[l - 1

];36}37

}3839 printf("

%d\n

", dp[1

][n]);40}

41return0;

42 }

poj 1738 石子合併(區間DP)

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

nyoj737 石子合併 區間dp

描述 有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入 有多組測試資料,輸入到檔案結束。每組測試資料第一行有乙個整數n,表示有n堆石子。接下來的一行...

acwing 282 石子合併(區間dp)

設有n堆石子排成一排,其編號為1,2,3,n。每堆石子有一定的質量,可以用乙個整數來描述,現在要將這n堆石子合併成為一堆。每次只能合併相鄰的兩堆,合併的代價為這兩堆石子的質量之和,合併後與這兩堆石子相鄰的石子將和新堆相鄰,合併時由於選擇的順序不同,合併的總代價也不相同。例如有4堆石子分別為 1 3 ...