是對線性區間的最優問題的處理,每乙個當前的區間的狀態都可以由之前的某個區間的狀態來處理即可。
寫狀態轉移方程的時候,有人是把最開頭的i當做和之前區間相比多出來的部分,有人把j當做和之前區間相比多出來的部分,兩者都行還是要看個人喜好。
dp[i]
[j]=
max(dp[i]
[j],dp[i]
[k]+ dp[k+1]
[j]+~~
~)
流傳比較廣的是兩種初始化方式,這裡以求區間的最小值為例,兩者並沒有什麼的大的區別,當然如果你是乙個模板化的玩家,我還是比較建議使用第一種,從崔神的揹包九講學過來的就會知道,初始化是講究乙個合法與非法的問題,對於非法的子問題,其值一定是inf,對於合法的那麼就是0,而第二種並沒有那種嚴格的狀態一說而已
整體初始化
memset
(dp,inf,
sizeof
(inf));
for(
int i =
1;i <= n;i++
) dp[i]
[i]=
0;
逐個初始化
memset
(dp,0,
sizeof
(dp));
//相當於沒有初始化
for(
int len =
1;len <= n;len++)}
}
之後的所有初始化問題均由讀者自己解決,不再贅述
好像有點模仿崔神(逃)
對於n個數,他們之間的間隔有n-1個,所以k並不能取到[i,j]的所有
對於一般的區間問題常見的就有兩種
for(int k = i;k < j;k++)
for(int k = i + 1;k <= j;k++)
dp的核心就是狀態轉移方程的書寫,但是很多人都不會寫,即使在見過很多題目之後也還是不會寫,沒思路,首先你要有乙個明確的概念,
當前的狀態都是由 最近的 之前的 狀態生成的
什麼意思呢,以一道題為例:
poj brackets (括號匹配)
題意:給定字串找到所有子串的括號匹配的數目最大值
思路:首先要確定是乙個線性的最優解的問題,其次就要想怎麼做,首先列舉起點,列舉長度,找到區間,那麼dp[i][j]如何才能永遠代表著當前區間的最大值呢,假設新加入的是起始節點 i,那麼當s[i]與s[j]匹配的時候,
dp[i][j] = dp[i+1][j-1] + 2;
不匹配就不需要更新,下一步是判斷怎麼個斷點取最優,第一步要明確
取斷點的目的在於什麼
在於將區間分割,得到最優的兩個子區間
比如:當前區間為 ( ) ( ( ) ) 那麼很明顯,我們分為哪兩個子區間的時候最大呢,肯定是從右往左第二個括號的左邊那裡分,但是計算機並不知道啊,他需要暴力求解啊,那麼怎麼個求解法則呢,就是列舉斷點不斷分割成左右兩個區間,取最大值即可。
是不是有點那意思了,接下來再看一道例題,再體會一下思想的昇華
hdu palindrome subsequence(回文子串數目)
一些超級基礎 常用的opencv功能
用慣了matlab,跑來用opencv真是各種不習慣。所以記錄一下一些常用的功能 作為積累。以下所有 均基於opencv 3.0。2016.7.26 將彩色影象轉為灰度圖 mat picture cvtcolor picture,picture,color bgr2gray 2016.8.20 1....
51nod 1201 整數劃分 超級好的DP題目
1201 整數劃分 基準時間限制 1 秒 空間限制 131072 kb 分值 80 難度 5級演算法題 將n分為若干個不同整數的和,有多少種不同的劃分方式,例如 n 6,共4種。由於資料較大,輸出mod 10 9 7的結果即可。input 輸入1個數n 1 n 50000 output 輸出劃分的數...
石子合併問題 一 (基礎的區間dp)
時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入有多組測試資料,輸入到檔案結束...