DP
動態規劃
簡單來說,動態規劃就是用空間換取時間。先把算過的答案存起來,再用原有的東西計算出新的,避免重複計算答案。
分析複雜度
- 狀態數
- 轉移式
- 把上面乘起來就是了
01 背包問題
有個背包能裝 W 重量的東西,有 n 樣物品,每種物品都有其價值 v 和重量 w,問能裝物品的最大價值?
最長公共子序列(LCS)
給定兩組序列:
s1 : a1, a2, a3, a4......
s2 : b1, b2, b3......
一個子序列 ai, aj, ak...... 滿足 i < j
舉例來說,7122, 712, 71, 7 的子序列可以是
7122, 71, 7、712, 71等等
現在問兩序列的最長公共子序列?
TIOJ
- 1007
- 1060
- 1354
- 1883
Longest Increasing Subsequence ( LIS )
- subsequence 指的是「子序列」
就是在一個數列中按照左右的相對位置,挑幾個數字出來 - increasing 指「嚴格遞增」
- 比如說「1, 3, 5, 2, 7, 8, 3, 9」中,
LIS 為 「1, 3, 5, 7, 8, 9」
- 一個一個找出後面能接上哪些數字
- 別擔心有複雜度更好的
O(n^{2})
O(n2)
int s[n], l[n]; // s = sequence, l = length
int LIS(){
for(int i = 0; i < n; i++) l[i] = 1;
for(int i = 0; i < n; i++){
for(int j = i+1; j < n; j++)
if(s[i] < s[j])
l[j] = max(l[j], l[i]+1);
}
int max = 0;
for(int i = 0; i < n; i++)
if(max < l[i]) l[i] = max;
return max;
}O(n logn)
O(nlogn)
vector<int> s;
int LIS(vector<int> s){
if(s.size() == 0) return 0;
vector<int> v;
v.push_back(s[0]);
for(int i = 1; i < s.size(); i++){
if(s[i] > v.back()) v.push_back(s[i]);
else *lower_bound(v.begin(), v.end(), s[i]) = s[i];
}
return v.size();
}滾動 DP
- 一種減少空間複雜度的技巧
UVa
- 103
- 111
- 231
- 437
TIOJ
- 1103
Dynamic Programming
By hfy880916
Dynamic Programming
- 607