組員:高珞洋,何汶珊
之前在學習分治法的時候也有將其和動態規劃進行比較,動態規劃能夠解題的根本要求是原問題可以細分成子問題,且原問題的最優解必包含子問題的最優解。
為了更明確上述條件,從而保證題目能夠運用動態規劃求解,通常需要兩步操作:
明確問題具有最優子結構,並分解問題
找出遞推關係式(狀態轉移方程),注意初始狀態即邊界條件
利用迴圈實現遞推關係
動態規劃的問題的難點就在於求遞推關係式,就個人經驗而言,有了遞推關係式後寫**就比較簡單了,大部分的解題時間也是花在求解和弄懂遞推關係上
對於求解動態規劃的問題,通常需要每次都保留所有可能的最優解。由於構成整體最優解必然包含區域性最優解,但是在全部解決方案列出前,我們不能確定當前的最優解就是整體最優解,因此需要對全部方案進行標記。
在**中,這一部分經常以「填表」的方式出現。我們利用額外的陣列儲存各個方案的最優解。比如最大子段和中有用maxsum[i]表示從第乙個元素開始到以第i個元素為結尾的子段和,在最長公共子串行中用maxsun[i][j]表示a串的前i個字元與b串的前j個字元的最長公共子串行。而我們在分析問題時,在找遞推關係之前,就要先明確這個額外的陣列儲存的是什麼樣的資訊。
//以下內容來自百科
由於動態規劃解決的問題多數有重疊子問題這個特點,為減少重複計算,對每乙個子問題只解一次,將其不同階段的不同狀態儲存在乙個二維陣列中。
此外,動態規劃由於由於遞推關係的存在,經常出現自頂向下分析,自底向上實現,例如數字三角形問題、最長公共子串行問題等。畢竟我們習慣從整體入手一步步向下細分問題,而程式則沒有第一步則無法實現整體。也就是說,在分析時我們需要確定,在某種特定情況下,只有一種最佳選擇,然後根據這個最佳選擇往前一步推導,在下一步的時候,往往是從多個結果中選擇最佳的結果,這點在數字三角形問題中有很明顯的體現。
動態規劃和分治法都要求問題可分割,區別在於動態規劃要求子問題並非相互獨立,比如我們總是追求最優解,而子問題的最優解會影響到當前問題的最優解,這點在最短編輯距離中體現明顯。
有了遞推關係式,為什麼不用遞迴呢?
事實上,有了遞推關係後,利用遞迴是完全能解決問題的,但是它和動態規劃相比時間卻大大增加,原因就在於遞迴進行了太多次重複運算。
遞迴解題的時候,假設我解第n個問題,需要從n-1,n-2...一直解到第1個問題,再將所有結果相加得到第n個問題的解。而這些步驟顯然在解第n-1個問題的時候都做過一遍,增加了許多無用開銷。
在動態規劃中,我們用陣列儲存最優解,即儲存了n-1的最優解,那麼當求解第n個問題的時候,直接呼叫n-1的最優解即可,大大降低了時間複雜度。這也是我們追求利用迴圈實現遞推關係而不用遞迴的原因。
3-1單調遞增最長子序列
定義ele[i]表示第i個元素,maxsub[i]表示第乙個元素到第ele[i]的最長單調遞增子串行的長度
從前開始往後掃瞄,將每個元素作為最後乙個元素,求此情況下的最長單調遞增子串行的長度,並以此作為乙個子問題,即每個maxsub[i]為乙個子問題。
在每個子問題中我們仍需要進行掃瞄,從第乙個元素掃到第i-1個數,設掃瞄的數為j,即0那麼我們要做的就是,如果ele[j]由此得出遞迴方程:
maxsub[i] = max (0在**實現中,需要額外變數來儲存max,不過為了圖方便,我直接把maxsub[j] + 1放到maxsub[i]中。這樣在求解maxsub[i]的時候,maxsub[i]當前的值就表示上乙個maxsub[j] + 1,這樣就只用比較maxsub[j] + 1和maxsub[i]了,即:
maxsub[i] = max (03-2 租用遊艇問題
定義cost[i][j]表示第i個租船點到第j個租船點的費用,min[i]表示從第i個租船點到終點的最小費用
這題一開始採用的演算法,需要用到乙個二維陣列來儲存每個租船點到終點的最小費用,但在參考了一些資料之後,發現可以採用更加簡潔易懂的演算法:
假設第i個租船點到終點的最低費用路徑為i-a-b-c-d-n(終點),那麼從第a個租船點到終點的最低費用路徑肯定是a-b-c-d-n(終點),依此類推,因此可以從終點往前推,即表min[i]從右往前填表
因此表min[i]要內儲存的資料為第i個租船點到終點的最低費用,則令min[i]=cost[i][i+1]+min[i+1],若cost[i][i+2]+min[i+2]結對程式設計老樣子分工明確,我負責**,珊爺輔助,她有問題及時提出,當我能把她講懂就說明我是真正理解的。偶爾她會有更好的想法,確實能改善程式。
但是在動態規劃方面的好處確實很大。有個人在旁面,你可以在邊推到遞推公式邊解釋,在分析的同時理清自己的思路,不容易出錯。
在敲**的時候,涉及到遞推公式也會詢問珊爺此處有無問題,算是二次檢查。
在遊艇問題中,一開始我用的二維陣列儲存最優解,也是珊爺表示這個問題和上乙個問題很相似,好像可以用一位陣列,我也才發現確實如此。
事實證明,在旁邊看你敲**的人並非什麼都不會。
參考貪心演算法和動態規劃的個人理解
經典中的經典演算法:動態規劃(詳細解釋,從入門到實踐,逐步講解)
演算法第三章作業
1.動態規劃是一種能夠減少重複運算的一種演算法,比較適合原問題能依賴於子問題解得,而子問題也能夠依賴於子子問題解得而出的問題。其次,動態規劃更適合於資料量較多的時候的一種演算法,當資料量沒有到達一定規模的時候,動態規劃演算法不能夠體現出足夠的優勢。如對於揹包問題的貪心演算法和動態規劃法 2.1 單調...
演算法第三章作業
我覺得動態規劃是一種分治法的偽高階型,它將乙個大問題可以分成若干個小問題後,解決子問題,然後將子問題的解插入到乙個表中,用乙個表來記錄所有的已經得到答案的子問題的解,後面就可以發現,無論子問題的解是否被用到,其都在表中,接著求問題便可以節省大量的時間。3 1m i 1 n 1 m i max 1 1...
演算法第三章作業
1.1 根據最優子結構性質,列出遞迴方程式。遞迴方程 len i max 0 j i ac 1 include2 using namespace std 3int dp int nums int n 13 14 15int max 1 16 for int i 0 i 20 21return max...