動態規劃之區間dp

2021-09-29 07:10:45 字數 4704 閱讀 2390

動態規劃(dp):

就是把把大問題轉化為乙個個小問題,然後在眾多的小問題中遞推得到這個大問題的最佳解(當然,這只是我個人對動態規劃的理解,希望有大牛來指導改正),那麼區間dp就是在區間之間進行動態規劃。

那麼區間dp的典型例題就是

nyoj 15 括號配對

nyoj 737 石子合併

做區間dp的題的一般步驟:

1.首先肯定開乙個dp[maxx][maxx]陣列,(區間dp一般是二維)dp[i][j]就是表示i到j這個區間的最優解,那麼dp[1][n]一般就是我們所要求的答案。

2.dp陣列的初始化是很重要的,根據題目要求,是全部賦值成0,還是-1,又或者是無窮大,但是更多的是(以dp[i][j]為例)ij時候為0,i=j時候是1(這個是說平常常用的初始化)。

3.這一步就是最關鍵的dp轉移方程,也沒啥好說的,知道很難找就對了(大佬請自動忽略…)。

4.剩下就是列舉子集和分割點,進過一系列列舉操作,就可以得到我們想要的答案了。

區間dp的一般模板:

int dp[maxx]

[maxx]

;void

init()

for(

int len=

1;len<=n;len++

)//列舉區間長度

}

題目

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

輸入

有多組測試資料,輸入到檔案結束。

每組測試資料第一行有乙個整數n,表示有n堆石子。

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

輸出

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

樣例輸入

31 2 3

713 7 8 16 21 4 18

樣例輸出

9239

ac**:

#include

#include

#include

#include

using

namespace std;

int a[

450]

;int dp[

450]

[450];

intmain()

for(

int i=

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

for(

int l=

1; l}printf

("%d\n"

,dp[1]

[n]);}

return0;

}

題目

給你乙個字串,裡面只包含"(",")","[","]"四種符號,請問你需要至少新增多少個括號才能使這些括號匹配起來。

如:是匹配的

()是匹配的

((]是不匹配的

([)]是不匹配的

輸入

第一行輸入乙個正整數n,表示測試資料組數(n<=10)

每組測試資料都只有一行,是乙個字串s,s中只包含以上所說的四種字元,s的長度不超過100

輸出

對於每組測試資料都輸出乙個正整數,表示最少需要新增的括號的數量。每組測試輸出佔一行

樣例輸入4

()((]

([)]

樣例輸出00

32ac**

#include

#include

#include

#include

using

namespace std;

int dp[

250]

[250];

char s[

150]

;int

panduan

(int x,

int y)

else

}int

main()

}for

(int i=

0;i<=

100;i++

)for

(int x=

1;x)for

(int k=i;k}printf

("%d\n"

,dp[1]

[l]);}

return0;

}

題目描述

在mars星球上,每個mars人都隨身佩帶著一串能量項鍊。在項鍊上有n顆能量珠。能量珠是一顆有頭標記與尾標記的珠子,這些標記對應著某個正整數。並且,對於相鄰的兩顆珠子,前一顆珠子的尾標記一定等於後一顆珠子的頭標記。因為只有這樣,通過吸盤(吸盤是mars人吸收能量的一種器官)的作用,這兩顆珠子才能聚合成一顆珠子,同時釋放出可以被吸盤吸收的能量。如果前一顆能量珠的頭標記為m,尾標記為r,後一顆能量珠的頭標記為r,尾標記為n,則聚合後釋放的能量為mrn(mars單位),新產生的珠子的頭標記為m,尾標記為n。

需要時,mars人就用吸盤夾住相鄰的兩顆珠子,通過聚合得到能量,直到項鍊上只剩下一顆珠子為止。顯然,不同的聚合順序得到的總能量是不同的,請你設計乙個聚合順序,使一串項鍊釋放出的總能量最大。

例如:設n=4,4顆珠子的頭標記與尾標記依次為(2,3) (3,5) (5,10) (10,2)。我們用記號⊕表示兩顆珠子的聚合操作,(j⊕k)表示第j,k兩顆珠子聚合後所釋放的能量。則第4、1兩顆珠子聚合後釋放的能量為:

(4⊕1)=1023=60。

這一串項鍊可以得到最優值的乙個聚合順序所釋放的總能量為

((4⊕1)⊕2)⊕3)=10* 2* 3+10* 3* 5+10* 5* 10=710。

輸入

有多組測試資料(<15),每組資料有兩行。每組資料的第一行是乙個正整數n(4≤n≤100),表示項鍊上珠子的個數。第二行是n個用空格隔開的正整數,所有的數均不超過1000。第i個數為第i顆珠子的頭標記(1≤i≤n),當i#include

#include

#include

#include

using

namespace std;

int a[

300][2

];int dp[

300]

[300];

intmain()

a[1]

[0]=a[n][1

];a[

1+n][0

]=a[n][1

];memset

(dp,0,

sizeof

(dp));

for(

int l=

1;l<

2*n;l++)}

}int maxx=0;

for(

int i=

1;i<=n;i++

)printf

("%d\n"

,maxx);}

return0;

}題目描述

判斷回文串很簡單,把字串變成回文串也不難。現在我們增加點難度,給出一串字元(全部是小寫字母),新增或刪除乙個字元,都會產生一定的花費。那麼,將字串變成回文串的最小花費是多少呢?

輸入

多組資料

第乙個有兩個數n,m,分別表示字元的種數和字串的長度

第二行給出一串字元,接下來n行,每行有乙個字元(a~z)和兩個整數,分別表示新增和刪除這個字元的花費

所有數都不超過2000

輸出

最小花費

樣例輸入

3 4abcb

a 1000 1100

b 350 700

c 200 800

樣例輸出

900

for(int j=0;j=0;i–)}}

這一段**,每一次外迴圈可以保證以前j位的字串變成回文串的代價最小,那麼讓j累加到m,就可以得到前m位的字串變成回文串的代價,也就是我們所要求出的答案。

ac**

#include

#include

#include

#include

using

namespace std;

int dp[

2105][

2105];

char s[

2105];

int a[

350]

;char z[2]

;int x,y;

intmain()

memset

(dp,0,

sizeof

(dp));

for(

int j=

0;j}printf

("%d\n"

,dp[0]

[m-1])

;}return0;

}

動態規劃 之 區間DP練習

loj 放上了那麼多 資訊學奧賽一本通 上的題 雖然我並沒有這本書 我要給它點乙個大大的贊 以後分類刷題不愁啦!那就一道道說吧。將 n 堆石子繞圓形操場排放,現要將石子有序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆的石子數記做該次合併的得分。求 n 1 次合併後得分總和的最大...

區間DP 動態規劃 C

區間型別動態規劃是線性動態規劃的拓展,它在分階段劃分問題時,與階段中元素出現的順序和由前一階段的哪些元素合併而來有很大的關係。1 合併 即將兩個或多個部分進行整合。2 特徵 能將問題分解成為兩兩合併的形式。3 求解 對整個問題設最優值,列舉合併點,將問題分解成為左右兩個部分,最後將左右兩個部分的最優...

模板 動態規劃 區間dp

因為昨天在codeforces上設計的區間dp錯了 錯過了上紫的機會 覺得很難受。看看學長好像也有學,就不用看別的神犇的了。區間dp處理環的時候可以把序列延長一倍。for int len 1 len n len 首先,使用四邊形優化要滿足下面的性質 當小區間包含在大區間中,則小區間的成本不高於大區間...