[線性DP]最長不下降子序列(LIS)
阿新 • • 發佈:2019-02-19
題目:
線上性動態規劃中狀態是一維的,第i個元素的狀態與前i-1個元素的狀態有關,前i-1個狀態組成一個決策序列,它是其他類動態規劃的基礎。典型的應用有LIS(最長不下降子序列),LCS(最長公共子序列)以及它們的應用。
例1 求最長不下降子序列。
由n個不相同的整陣列成的數列,記為:a(1),a(2),…,a(n)且a(i)≠a(j)(i≠j),例如,3,18,7,14,10,12,23,41,16,24.若存在i1<
i2<i3<…<ie且有a(i1)<a(i2)<…<a(ie),則稱其為長度為e的不下降子序列。如上例中3,18,23,24就是一個長度為4的不下降子序列,同時也有3,7,10,12,16,24長度為6的不下降子序列。程式要求,當原數列給出之後,求出最長的不下降子序列的資料個數。
輸入檔案:
第一行為N(1≤N≤5000),第二行為N個整數,之間用空格隔開。
輸出檔案:
最長的不下降子序列的資料個數。
輸入樣例:
10
3 18 7 14 10 12 23 41 16 24
輸出樣例:
6
思路:DP入門題,狀態轉移方程:f[i] = max{ f[j] } + 1 (1 <= j < i);
狀態轉移方程f[i] = max{ f[j] }+1 要求a[j] < a[i], 那a[j] > a[i]怎麼辦?
我一開始有這樣的疑問,其實是對 f[i] 有誤解:
f[i] 不代表到 i 位置為止的最長不下降子序列的個數
f[i] 代表以 a[i] 為結尾
程式碼:
#include <iostream> #include <stdio.h> #include <map> #include <vector> using namespace std; /* 狀態轉移方程f[i] = max{f[j]} +1 (1 <= j < i); f[i] 代表以 a[i] 結尾的最長不下降子序列 最後只需要遍歷一遍f[0~n-1]最大的是誰就好 */ int f[20]; int maxn; int n; void LIS_dp(int *a) { for(int i = 0; i < n; i++) { f[i] = 1; for(int j = 0; j < i; j++) { if(a[i] > a[j] && f[j]+1 > f[i]) f[i] = f[j] + 1; } } } int main() { int a[10]; scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &a[i]); LIS_dp(a); int t = 0; for(int i = 0; i < n; i++) if(f[i] > t) t = f[i]; printf("%d", t); return 0; } /* 10 3 18 7 14 10 12 23 41 16 24 */
反思:
關注 f[i] 或者 f[i][j] 等所代表的確切意思