每日一題 石子合併 區間DP

2022-04-29 05:45:11 字數 1733 閱讀 1092

區間dp我也不會,哈哈,正好一起學習一下,做一下這道區間dp入門題。
區間dp其實也是線性dp的一種,只是由於其實在太規律,所以分成一類以方便學習!!

要點:狀態必然包含區間是哪個[i,j],通過列舉區間分界點進行轉移。 也就是說乙個大區間是由兩個子區間合併來的或者是兩個子區間加上中間元素合併來的!在合併 的時候自然是要滿足最優化原理和無後效性原則…… 不能多說,到題目中去體會! 這類問題經常會遇到環,環的處理辦法通常有兩種: 謱)加倍——將資料複製加倍,就可以保證最後乙個與第乙個相連; 謲)取餘——在呼叫陣列時對n取餘。 有可能需要提前處理合併區間的費用,如何處理視情況而定,不要忘記預處理和字首和的辦法! 經典例題有:石子合併,數鏈剖分,括號匹配,田忌賽馬謬 凸多邊形三角劃分等

以上內容均摘要 dsy -- 雨神 大佬

區間 dp 嘛,我們都知道 dp 是由多個子問題最終組合成乙個大的問題,並且滿足無後效性等多種特性(菜雞的淺顯理解)

那麼對於區間dp 來說,道理依然如此,即分成若干個子區間,子區間組成乙個大的區間最後形成乙個總區間。

(由於自己dp太菜,目前水平還尚未達到,即使基礎的題目來說,也需要先參考一下別人寫的,如有寫的不到位的

地方,望各位路過的大佬能夠不吝賜教)

對於這道題,先看一下資料範圍,10^2,那麼我們完全可以走雙重迴圈甚至三重迴圈的線路。

當然也可以嘗試著用 dfs 搞一搞。

我們發現(實際上是大佬們發現),大的方面來說,每一堆石子都是由兩堆石子組成的,

也就是說 l ~~ r 這一堆石子是由 l ~ k + (k + 1) ~ r 這兩堆石子組成的,但是中間

的 k 可能有很多堆,我們不知道 l 和 r 將 哪個 k 作為中間的分界點然後可以使得總代

價最小,所以我們需要去列舉所有可能的情況。

我們可以從小到大列舉所有區間,從而做到不重不漏(與線段樹類似)

具體看**吧.

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

const int maxn = 305;

int dp[maxn][maxn];

int a[maxn],sum[maxn];

int n;

/* dp[i][j]: 把最初的第 i 堆 ~ 第 j 堆石子合併為一堆,所花費的最小代價

(實際上就是乙個集合,從小到大列舉長度實際上相當於一堆一堆

合併)

*/ int main(void)

// 長度為 1 時不用合併,所以直接從 2 開始

// 列舉長度

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

// 將兩堆合併為 1 堆時所付出的代價

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

} }

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

return 0;

}

石子合併(區間DP板子題)

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

石子合併 (區間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...