動態規劃的基本思想算法
動態規劃的基本思想在於發現和定義問題中的子問題,這裏子問題可也以叫作狀態;以及一個子問題到下一個子問題之間 是如何轉化的 也就是狀態轉移方程數組
所以咱們遇到一個問題的時候 應該想想這個問題是否能用某種方式表示成一個小問題,而且小問題具備最優子結構spa
最優子結構:問題的最優解由相關子問題的最優解組合而成,這些子問題能夠獨立求解orm
關於最優子結構 咱們來看2個示例blog
一、求無權有向圖中q-t的最短路徑遞歸
若是q-t間的最短路徑通過了點w 那麼咱們能夠證實 q-w w-t也均是最短路徑 字符串
因此無權有向圖最短路徑是具備最優子結構的it
二、求無權有向圖中q-t的最長的路徑im
而無權有向圖最長路徑中 總結
q-t的最長路徑是是q-r-t 但 q-r缺不是q-r的最長路徑 q-s-t-r是一條更長的路徑
因此無權有向圖最長路徑不具備最優子結構
二、關於動態規劃的另外一個要點即是思考稍小的子問題和下一個子問題間是如何轉化的也就是如何定義狀態轉移方程
狀態轉移方程的定義和咱們是如何定義子問題的有關
好比:求最長連續迴文串: 給出一個字符串S,求最長的連續迴文串,例如串 babcbabcbaccba 最長迴文是:abcbabcba
咱們若是定義
p( i ) :以i結尾的最長迴文串 咱們會發現咱們用子問題沒法表示出p(i+1)
咱們從新考慮一下原問題 最長連續迴文串 若是用另外一種方式來從新定義這個問題
已知字符串 S[0,n] 求迴文傳S[i,j]中最長的那一個
咱們能夠定義如下子問題
P(i,j) : S[i,j] 是不是一個迴文, P(i,i) = true
那麼咱們能夠定義以下的狀態轉換方程
P(i,j) ={ (P(i+1,j-1) && (Si == Sj) }
總結起來咱們能夠用如下步驟去考慮一個問題如何用動態規劃來解決
一、思考問題的最後一個步驟 是如何經過選擇構造獲得最終答案的
二、根據構造狀況來發現子問題
三、看看可否肯定狀態轉移方程
動態規劃與貪心等其餘算法的比較
動態規劃與分治,減治
分治 :將大問題分紅若干個小問題去解決 遞歸的求解每一個小問題,每一個小問題之間沒有關係 例如 快排
減治 :將大問題縮減成小問題,減掉的部分不須要考慮,例如:二分查找
動態規劃:將原問題分紅多個子問題,不一樣子問題間存在必定的聯繫,相互間有重疊的子問題
這裏我我的認爲動態規劃分治 減治都是將大問題拆分紅小問題 進行求解 區別在於
減治法減掉的部分 能夠不用再求解了;
分治法每一個小問題都須要進行求解;
動態規劃不一樣的子問題間是有相互重疊的子問題的
動態規劃與貪心
動態規劃在於咱們求解了全部子問題 雖然有些子問題最終並不能組成答案
而貪心算法任務無需求解全部子問題,因此選擇在當前狀況下最優的狀況自頂向下的求解問題,貪心能夠認爲是動態規劃的一個特例
若是用一個樹來表示子問題的話 能夠認爲動態規劃考慮了樹中的全部節點
而貪心算法減去了樹了許多枝幹,在考慮了通向最優解的那一條路
常見的能夠用動態規劃解決的問題
一、最大連續子序列和:
給定k個整數的序列{N1,N2,...,Nk },其任意連續子序列可表示爲{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k。最大連續子序列是全部連續子序中元素和最大的一個,
例如給定序列{ -2, 11, -4, 13, -5, -2 },其最大連續子序列爲{11,-4,13},最大連續子序列和即爲20。
二、最大連續子序列乘積:
給一個浮點數序列,取最大乘積連續子串的值,例如 -2.5,4,0,3,0.5,8,-1,則取出的最大乘積連續子串爲3,0.5,8。也就是說,上述數組中,3 0.5 8這3個數的乘積30.58=12是最大的,並且是連續的。
三、求最長連續迴文串:
給出一個字符串S,求最長的連續迴文串,例如串 babcbabcbaccba 最長迴文是:abcbabcba
四、字符串類似度:
五、最長公共子序列
對於序列S和T,求它們的最長公共子序列。例如X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A}則它們的lcs是{B,C,B,A}和{B,D,A,B}。求出一個便可。
針對最大連續子序列乘積給出一段講解與代碼
最大連續子序列和:
給定k個整數的序列{N1,N2,...,Nk },其任意連續子序列可表示爲{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k。最大連續子序列是全部連續子序中元素和最大的一個,
例如給定序列【-2, 11, -4, 13, -5, -2】,其最大連續子序列爲{11,-4,13},最大連續子序列和即爲20。
思路:
20這個答案 是咱們比較了【-2】,【11】,【-4】,【-2,11,-4,11】,【11,-4,13】,【11,-4,13,-5】,【11,-4,13,-5。-2】這幾個序列以後獲得
因此咱們定義子問題是
Max(i) : 以i結尾的連續序列的最大和
狀態轉移方程是:
Max[i] = max{a[i], Max[i-1] + a[i])
代碼以下:
int maxSubArray(int A[], int n) {
int ans=A[0],i,j,sum=0;
for(i=0;i<n;i++){
sum+=A[i];
ans=max(sum,ans);
sum=max(sum,0);
}
return ans;
}