區間dp,顧名思義,就是在區間上dp,即把整個區間劃分為乙個個的小區間,在小區間內dp求出最優值,然後把這些小區間合併以後就是整個取件的最優值。
下面是一些比較經典的區間dp題目:
1.nyoj 737 石子合併:
題意:有n堆石子,每堆有a[i]個,每次合併時只能合併相鄰的兩堆,代價為兩堆石子的個數之和。問把這n堆石子合併成一堆需要的最小代價是多少。
狀態:dp[i][j] 表示合併第 i 堆到第 j 堆石子的最小代價
轉移方程;dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]);
其中sum[i]表示前i堆石子的總個數。
#include#include#includeusing namespace std;
#define inf 0x3fffffff
const int n = 205;
int a[n], sum[n], dp[n][n];
int main()
for(int l = 2; l <= n; l++)
}printf("%d\n",dp[1][n]);
}return 0;
}
2.poj 2955 brackets
題意:給出一串由『(『,』)『,』[',『]』組成的字串,問最多有多少個括號匹配。
狀態:dp[i][j]表示 i 到 j 最多的匹配個數
轉移方程:dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j]);
#include#include#includeusing namespace std;
const int n = 105;
char str[n];
int dp[n][n];
bool judge(char a, char b)
int main()
for(int k = 2; k < len; k++) //列舉子串的長度
}printf("%d\n",dp[0][len-1]);
}return 0;
}
3.poj 1141 brackets sequence
題意:給出一串由『(『,』)『,』[',『]』組成的字串,求使原串裡面的括號全部匹配後的長度最短的字串。
狀態:dp[i][j] 表示使 i 到 j 全部匹配最少需要新增的括號個數。
轉移方程:dp[i][j] = min(dp[i][j], dp[i][k] + dp[i+1][k]);
#include#include#define inf 0x3ffffff
const int n = 105;
char str[n];
int dp[n][n], flag[n][n];
bool judge(char a, char b)
void print(int i, int j)
else if(flag[i][j] == -1)
else
}int main()
for(int k = l; k < r; k++)
if(dp[l][r] > dp[l][k] + dp[k+1][r])
dp[l][r] = dp[l][k] + dp[k+1][r], flag[l][r] = k; //flag[l][r]=k表示以k為分割點的兩端的匹配之和最優}}
//printf("%d\n",dp[0][len-1]);
print(0, len-1);
printf("\n");
}return 0;
}
線性dp 區間dp
1 尼克的任務 額一道挺水的題,愣是做了幾個小時 動態規劃大致的思路還是找乙個轉移 換個詞就是影響 我們可以明顯看出本題的規則 空暇時,一遇到任務必須挑乙個接 求1 n時間內最大空暇時間 所以將任務排序是必要的,兩個關鍵字 再來想象一下當我做到第i 個任務時,我在 st i st i t i 1 時...
線狀DP及區間DP
這裡我們都用到動態規劃的思想 dynamic programming,簡稱dp。本質就是組合子問題來求解原問題,且對每個子問題只求解一次。一般來說四個步驟 1.刻畫乙個最優結構特徵 2.遞迴的定義最優解值 3.計算最優解的值 4.利用計算出的資訊構造乙個最優解 這邊直接給出 include incl...
區間DP結構
區間動態規劃問題一般都是考慮,對於每段區間,他們的最優值都是由幾段更小區間的最優值得到,是分治思想的一種應用,將乙個區間問題不斷劃分為更小的區間直至乙個元素組成的區間,列舉他們的組合 求合併後的最優值。設f i,j 1 i j n 表示區間 i,j 內的數字相加的最小代價 最小區間f i,i 0 乙...