最長遞增子序列是動態規划中經典的問題,詳細如下:
在一個已知的序列{a1,a2,...,an}中,取出若干數組組成新的序列{ai1,ai2,...,aim},其中下標i1,i2,...,im保持遞增,即新數列中的各個數之間依舊保持原數列中的先后順序,那么我們稱新的序列{ai1,ai2,...,aim}為原序列的一個子序列。若在子序列中,當下標ix > iy時,aix > aiy,那么我們稱這個子序列為原序列的一個遞增子序列。最長遞增子序列問題,就是在一個給定的原序列中,求得最長遞增子序列長度。
有序列{a1,a2,...,an},我們求其最長遞增子序列長度。按照遞推求解的思想,我們用F[i]代表若遞增子序列以ai結束時它的最長長度。當 i 較小,我們容易直接得出其值,如 F[1] = 1。那么,如何由已經求得的 F[i]值推得后面的值呢?假設,F[1]到F[x-1]的值都已經確定,注意到,以ax 結尾的遞增子序列,除了長度為1的情況,其它情況中,ax都是緊跟在一個由 ai(i < x)組成遞增子序列之后。要求以ax結尾的最長遞增子序列長度,我們依次比較 ax 與其之前所有的 ai(i < x), 若ai小於 ax,則說明ax可以跟在以ai結尾的遞增子序列之后,形成一個新的遞 增子序列。又因為以ai結尾的遞增子序列最長長度已經求得,那么在這種情況下,由以 ai 結尾的最長遞增子序列再加上 ax 得到的新的序列,其長度也可以確定,取所有這些長度的最大值,我們即能得到 F[x]的值。特殊的,當沒有ai(i < x)小 於ax, 那么以 ax 結尾的遞增子序列最長長度為1。 即F[x] = max{1,F[i]+1|ai<ax && i<x};
例如序列{1,4,3,2,6,5}的最長遞增子序列長度的所有F[i]為:
F[1] (1) | F[2](4) | F[3](3) | F[4](2) | F[5](6) | F[6](5) |
1 | 2 | 2 | 2 | 3 | 3 |
總結一下,求最長遞增子序列的遞推公式為:
F[1] = 1;
F[i] = max{1,F[j]+1|aj<ai && j<i}
我們可以根據遞推公式將算法實現
#include <iostream> using namespace std; const int MAXSIZE = 10; const int MIN = 0; int arr[] = { 1, 4, 3, 2, 6, 5 }; int F[MAXSIZE]; int main() { int maxLen = MIN; memset(F, 0, MAXSIZE); F[0] = 1; for (int i = 1; i < 6; i++) { for (int j = 0; j < i; j++) { if (arr[i] > arr[j] && maxLen < F[j]) { maxLen = F[j]; } } F[i] = maxLen + 1; } for (int k = 0; k < 6; k++) cout << F[k] << ' '; cout << endl; }