區間DP入門題目合集

2022-05-11 15:21:33 字數 3331 閱讀 4573

區間dp主要思想是先在小區間取得最優解,然後小區間合併時更新大區間的最優解。

基本**:

//

mst(dp,0) 初始化dp陣列

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

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

區間長度

for(int i=1;i<=n;i++) //

列舉起點

}

51nod - 1021 石子歸併(區間dp)

【題目描述】

n堆石子擺成一條線。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的代價。計算將n堆石子合併成一堆的最小代價。

例如: 1 2 3 4,有不少合併方法

1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)

1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)

1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)

sample input

412

34

sample output

19
預處理出區間和,然後列舉每個長度的區間和斷點,轉移即可。

f[i][j] = min(f[i][j], f[i][k]+f[k+1][j]+sum[j]-sum[i-1])

#include #include 

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;const

int maxn = 1000 + 100

;#define inf 0x3f3f3f3f

intmain()

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

}printf(

"%d\n

", f[1

][n]);

}

view code

uva - 10003 cutting sticks

題意:有一根長度為 n 的木棍,m 個可以切開的位置。

如果把乙個長木棍切成兩根短木棍,那麼花費就是那根長木棍的長度。

求把這根木棍按照 m 個切點全部切開的最小花費。

#include #include 

#include

#include

#include

using

namespace

std;

#define maxn 100 + 100

#define inf 0x3f3f3f3f

intmain()

for (int len = 2; len <= m+1; len++)

for (int i = 0; i+len <= m+1; i++)

printf(

"the minimum cutting is %d.\n

", f[0][m+1

]); }

}

view code

noip 2006 提高組 - 能量項鍊

有一串首位相連的環形能量珠項鍊,每個能量珠由頭部和尾部組成。相鄰的能量珠必定是某乙個的頭部 = 另乙個的尾部。

可以把兩個相鄰的能量珠(a,b)(b,c)合成乙個新的能量珠(a, c),並且釋放 a * b * c的能量。

操作這串能量珠能夠獲得的最大的總能量是多少?

樣例中,四個能量珠分別為(2, 3) (3, 5) (5, 10) (10, 2)

對於環形區間,我們只要把它展開成線形區間進行dp,然後取 dp[i, i+n-1] 中的最大值就可以了。

#include #include 

#include

#include

using

namespace

std;

#define maxn 200 + 100

#define inf 0x3f3f3f3f

intmain()

a[2*n+1] = a[1

];

for (int i = 1; i <= 2*n; i++)

for (int j = i; j <= 2*n; j++)

f[i][j] = 0

;

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

for (int i = 1; i+len-1

<= 2*n; i++)

int ans = 0

;

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

ans = max(ans, f[i][i+n-1

]); printf(

"%d\n

", ans);}}

view code

hdu - 3506 monkey party

也是普通的環形區間dp,拆環為鏈。

然而這樣過不了的。因為資料範圍是2000,n^3的dp會tle。

所以需要用平行四邊形優化。

這個玩意我還沒有看懂,只是拿過來用。以後慢慢理解。

#include #include 

#include

#include

using

namespace

std;

#define maxn 2000 + 100

#define inf 0x3f3f3f3f

intmain()

for (int i = 1; i <= 2*n; i++)

sum[i] = sum[i-1] +a[i];

for (int i = 1; i <= 2*n; i++)

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

for (int i = 1; i+len-1

<= 2*n; i++)}}

int ans =inf;

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

ans = min(ans, f[i][i+n-1

]); printf(

"%d\n

", ans);}}

view code

區間DP值入門題目 石子歸併

這兩天特別喪,不想學習,心態有點崩。不知道為什麼,可能是假期綜合症吧,又感覺自己處在了一種極度的迷茫之中,都怪袁老,讓我自己一天吃飽了沒事幹,胡思亂想,嗚嗚嗚.jpg。區間dp 區間dp就是在區間上的動態規劃,求解一段區間上的最優解,通過合併小區間的最優解來得到整個大區間上的最優解的演算法。時間複雜...

區間DP入門

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

區間DP入門

今天學長給我們講了區間dp,當然聽得雲裡霧裡,講完之後基本處於自閉狀態,然後還是自己到大佬的部落格,然後看部落格,但是並沒有找到很詳細的部落格,所以我想自己寫一寫,大神們勿噴哈.一 定義 區間dp,顧名思義是在區間上dp,它的主要思想就是先在小區間進行dp得到最優解,然後再利用小區間的最優解合併求大...