學動態規劃自然要從數字三角形開始起步,那麼我們就先從數字三角形開始。
數字三角形題目:有乙個由非負整數組成的三角形,第一行只有乙個數,除了最下行之外的每個數的左下方和右下方各有乙個數,如下圖所示:
3 24 10 1
4 3 2 20
從第一行的數開始,每次可以往下或往右下走一格,直到走到最下行,把沿途經過的數全部加起來。如何走才能使這個和最大?
知道回溯法麼(請參看:八皇后與回溯法),你會發現這是乙個動態的決策問題:每次有兩種選擇——向左或是向右,每一步決策又影響到後面的決策,如果用貪心,你會發現由區域性最優解得不到全域性最優解,所以本題要麼用回溯法(但是回溯法的效率太低,特別是基數大的時候,讓人無法忍受),要麼就是用動態規劃。
我們用d(i,j)表示從格仔(i,j)出發到達底層能取得的最大和,用a(i,j)表示當前格仔的權值,從格仔(i,j)出發有兩種決策,如果往左走,則到(i+1,j)後需要求從(i+1,j)往後走能得到的最大和,即d(i+1,j);如果往右走,則需要求從d(i+1,j+1)開始出發能取得的最大和,即d(i+1,j+1)。由於可以在這兩個決策中自由選擇,所以應該選擇d(i+1,j)和d(i+1,j+1)中較大的乙個。至此,我們得出了動態規劃解題中最重要的狀態轉移方程:
d(i,j)=a(i,j)+ max(d(i+1,j),d(i+1,j+1))
如果往左走,那麼最好的情況等於(i,j)格仔裡的值a(i,j)與d(i+1,j)之和,如果從格仔(i+1,j)出發到底層這部分的和都不是左右決策中最大的,那麼加上a(i,j)之後的值也不會是最大的。這個性質稱之為最優子結構,也可以描述成「全域性最優解包含區域性最優解」。
那麼我們看第一種方法(遞迴法)
[cpp]view plain
copy
print?
#include
#define maxn 100
using
namespace std;
int a[maxn][maxn],n;
int d(int i,int j)
int main()
#include
#define maxn 100 using namespace std; int a[maxn][maxn],n; int d(int i,int j) int main()
#include
#define maxn 100 using namespace std; int a[maxn][maxn],d[maxn][maxn]; int main()
} int main()
#include
#define maxn 100 using namespace std; int a[maxn][maxn],d[maxn][maxn],n; int memy(int i,int j) } int main()
cout
}
#include
#define maxn 110 using namespace std; int main() cout把程式和圖結合起來看,01揹包問題就會十分簡單易懂,什麼描述都不如一張圖來得爽快直接。
我們還可以邊讀入資料邊計算,而不必把v和w儲存下來,只需要改動乙個地方即可。
[cpp]view plain
copy
print?
#include
#define maxn 110
using
namespace std;
int main()
} cout
}
#include
#define maxn 110 using namespace std; int main() } cout<
如果繼續優化空間,我們可以用一維陣列來儲存計算資訊。
[cpp]view plain
copy
print?
#include
#define maxn 110
using
namespace std;
int main()
} cout
}
#include
#define maxn 110 using namespace std; int main() } cout<
本文部分地方引用了《揹包九講》、《演算法競賽入門經典》。
動態規劃入門
1 用 dp 做的題大多數返回值是int boolean,求max min,不能打亂原來輸入順序。2 動態規劃有兩個重要定義,乙個叫 optimal substructure 另乙個叫 overlap subproblem 各種排序 tree 類問題中,都會用到 divide conquer 的思想...
動態規劃入門
大家可以看看這篇文章dp,哪個更容易理解就看哪個!一 動態規劃的定義 動態規劃程式設計是一種針對於解決最優化問題的一種途徑 一種方法,而不是一種特殊演算法,也就是說它沒有固定的模板。在動態規劃中,每走一步都要看看能不能最優,而且動態規劃最擅長的就是多階段問題!二 動態規劃的基本概和基本模型構成 1....
動態規劃入門
最長公共子串行 lcs lcs 遞迴 int findlcs string a,int n,string b,int m 採用動態規劃的策略o n m 將計算的方向顛倒,將遞迴改為迭代 0 將所有子問題 假想地 列成一張表 1 顛倒計算方向,從lcs a 0 b 0 出發依次計算出所有項。遞迴公式1...