區間DP入門

2021-08-22 10:27:42 字數 2653 閱讀 3421

今天學長給我們講了區間dp,當然聽得雲裡霧裡,講完之後基本處於自閉狀態,然後還是自己到大佬的部落格,然後看部落格,但是並沒有找到很詳細的部落格,所以我想自己寫一寫,大神們勿噴哈.

一 .定義

區間dp,顧名思義是在區間上dp,它的主要思想就是先在小區間進行dp得到最優解,然後再利用小區間的最優解合併求大區間的最優解。

//一般區間

dp實現**

規定 dp[i][j] 為區間[i,j] 上的最優解

for(int

i =

1; i <= n; i++)//

區間長度為

1的初始化

dp[i][i] = x;                                

// x

視情況而定

for(int

len =

2; len <= n; len++)              

//列舉區間長度

} 1. 石子合併

有n堆石子,現要將石子有序的合併成一堆,規定如下:每次只能移動

相鄰的2堆石子合併,合併花費為新合成的一堆石子的數量。求將這n堆石子合併成一堆的總花費最小(或最大)。

引入區間dp

區間dp的思想是 利用一次次的合併過程去更新所得的結果,以便下一次合併使用。

從小的區間一點一點分析

設 a[i] 為第i堆的石子數目 1

.若有一堆石子,無需合併 花費為 0 2

.若有兩堆石子,將這兩堆合併  花費為a[0] + a[1] 3

.若有三堆石子,有兩種情況   4

.若有四堆石子,有三種情況  ……

分析一下演算法過程   

dp 二維陣列 ,橫座標代表區間起點,縱座標代表區間終點 . 比如: dp[1][2] 代表 第一堆石子到第二堆石子的最優解,下面詳細說吧,

可能這樣提前說不太理解.

首先 最外層迴圈 控制石子堆的長度(len = 2 to n)  

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

第二層迴圈,確定區間起點與終點

for(int i=1,j=len;j<=n;++i,++j)

經過分析還需要一層迴圈,列舉將區間分割的那個點k

for(int k = i;k最後來看這個動態轉移方程

dp[i][j] : 區間[i,j]上的石子合併最小花費

sum[i][j]: 區間[i,j] 的和

dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j] + sum[i][j]);         

動態轉移方程可以這麼理解  現在已經將第 i 堆到第k堆 、 第k+1堆到第j堆合併了,現在只剩下這兩堆  要將這兩堆去合併

那麼就是利用之前算出來的dp[i][k] + dp[k+1][j] 再加上區間[i,j]的和

為什麼是加區間[i,j]的和呢   你把[i,k] 和[k+1,j]的石子合併到了一起

合併這兩個區間的花費一定是這兩個區間的總石子數,當然也就是[i,j]總石子數。

過程 :

1   初始化 dp陣列

過程 :

整個過程就這樣的 ,不斷的更新小區間最優解,然後最總就可以得到大區間的最優解.

鏈結 :  

** : 

#include #include #include #include #include #include #define d(x) for(int i = 1 ;i<=(x) ; i++)

#define init_(x) memset(x,0,sizeof(x))

#define pi acos(-1)

#define while_(x) while(scanf("%d",&x)!=eof)

#define while_c(x) while(x--)

#define scanf_(x,y) scanf("%d%d",&x,&y)

#define mst(a,b) memset((a),(b),sizeof(a))

using namespace std ;

const int inf = 1<<30 ;

typedef long long ll ;

const ll mod = 1e9+7 ;

int dp[1005][1005] ;

int sum[1005] ;

int main()

for(int len = 2 ;len<=n ; len++) // 區間長度

{ for(int i = 1 ; i<=n ; i++)// 列舉起點

{ int j = len-1+i ; // 區間終點

if(j>n)

continue; // yuejie

for(int k = 1 ; k今天先寫到這裡,等學了其他的再加補充.

區間DP入門

區間dp,看名字其實會聯想到劃分dp,其實兩者的關係並不大。劃分dp是從頭到尾劃分解決,並且有劃分數量,而區間dp沒有這些限制條件,可以從任意區間開始,一直擴大到整個區間。不斷遞推求解。同樣也是分兩步去做。首先 還是進行資料處理,比如用陣列sum i j 去儲存i到j的和,或者是用別的方式處理並儲存...

區間dp入門

區間dp就是區間上的dp,先算出小區間的最優解,再由小區間合併推出大區間的最優解。include include include includeusing namespace std const int inf 0x3f3f3f3f const int maxn 1010 int n int a m...

區間DP入門

給你乙個只含小寫字母的字串,每次只能刪除一段含有一樣字母的區間,問最少刪多少次,才能刪除整個字串 第一次做區間dp 所以記錄詳細點 適合新手 我們用dp i j 代表把區間 i 到 j 完全刪除需要的次數 狀態轉移方程 if s i s j dp i j dp i 1 j 1 1 兩頭一樣,我們把中...