最长下降/上升子序列问题
最長下降/上升子序列
開始的時鐘永遠(yuǎn)為你的奮斗時刻準(zhǔn)備著,只要你需要它
這題目是經(jīng)典的DP題目,也可叫作LIS(Longest Increasing Subsequence)最長上升子序列或者 最長不下降子序列。很基礎(chǔ)的題目,有兩種算法,復(fù)雜度分別為O(n*logn)和O(n^2) 。
一.問題描述
設(shè)有由n個不相同的整數(shù)組成的數(shù)列,記為: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的不下降序列。程序要求,當(dāng)原數(shù)列給出之后,求出最長的不下降序列。二.算法分析(一)。根據(jù)動態(tài)規(guī)劃的原理,由后往前進(jìn)行搜索。1·對a(n)來說,由于它是最后一個數(shù),所以當(dāng)從a(n)開始查找時,只存在長度為1的不下降序列;2·若從a(n-1)開始查找,則存在下面的兩種可能性:①若a(n-1)<a(n)則存在長度為2的不下降序列a(n-1),a(n)。②若a(n-1)>a(n)則存在長度為1的不下降序列a(n-1)或a(n)。3·一般若從a(i)開始,此時最長不下降序列應(yīng)該按下列方法求出:在a(i+1),a(i+2),…,a(n)中,找出一個比a(i)大的且最長的不下降序列,作為它的后繼。倒推公式為
F(I)=MAX{F(I+K)}+1
F[I]:表示以第I個位置為起點(diǎn)的最長不下降序列的長度。
K的選擇范圍:a(I+k)>a(i) I+k≦n
最后從F[1]到F[N]中選取最大的即為最優(yōu)解
當(dāng)然也可以采用順推的方法,順推公式為
F(I)=MAX{F(I-K)}+1
F[I]:表示以第I個位置為終點(diǎn)的最長不下降序列的長度。
K的選擇范圍:a(I-k)<a(i) I-k≧1
最后從F[1]到F[N]中選取最大的即為最優(yōu)解
4·為算法上的需要,定義一個數(shù)組(倒推法)整數(shù)類型二維數(shù)組d(N,3)d(I,1)表示點(diǎn)a(i)d(I,2)表示從I位置到達(dá)N的最長不下降序列長度d(I,3)表示從I位置開始最長不下降序列的下一個數(shù)字的位置,以便打印。初始化:FOR I = 1 TO NINPUT #1, D(I, 1)D(I, 2) = 1D(I, 3) = 0NEXT IA.O(n^2)算法分析如下:
(a[1]...a[n] 存的都是輸入的數(shù))
1、對于a[n]來說,由于它是最后一個數(shù),所以當(dāng)從a[n]開始查找時,只存在長度為1的不下降子序列;
2、若從a[n-1]開始查找,則存在下面的兩種可能性:
(1)若a[n-1] < a[n] 則存在長度為2的不下降子序列 a[n-1],a[n];
(2)若a[n-1] > a[n] 則存在長度為1的不下降子序列 a[n-1]或者a[n]。
3、一般若從a[t]開始,此時最長不下降子序列應(yīng)該是按下列方法求出的:
在a[t+1],a[t+2],...a[n]中,找出一個比a[t]大的且最長的不下降子序列,作為它的后繼。
4、為算法上的需要,定義一個數(shù)組:
int d[n][3];
d[t][0]表示a[t];
d[t][1]表示從i位置到達(dá)n的最長不下降子序列的長度;
d[t][2]表示從i位置開始最長不下降子序列的下一個位置。
實(shí)現(xiàn)代碼如下:
include
using namespace std;
int main(void)
{
int i,j,n,a[100],b[100],max;
while(cin>>n)
{
for(i=0;i<n;i++)
cin>>a[i];
b[0]=1;//初始化,以a[0]結(jié)尾的最長遞增子序列長度為1
for(i=1;i<n;i++)
{
b[i]=1;//b[i]最小值為1
for(j=0;j<i;j++)
if(a[i]>a[j]&&b[j]+1>b[i])
b[i]=b[j]+1;
}
for(max=i=0;i<n;i++)//求出整個數(shù)列的最長遞增子序列的長度
if(b[i]>max)
max=b[i];
cout<<max<<endl;
}
return 0;
}
顯然,這種方法的時間復(fù)雜度仍為o(n^2);
例題:NOIP1999(dp入門經(jīng)典)
題意:某國為了防御敵國的導(dǎo)彈襲擊,發(fā)展出一種導(dǎo)彈攔截系統(tǒng)。但是這種導(dǎo)彈攔截系統(tǒng)有一個缺陷:雖然它的第一發(fā)炮彈能夠到達(dá)任意的高度,但是以后每一發(fā)炮彈都不能高于前一發(fā)的高度。某天,雷達(dá)捕捉到敵國的導(dǎo)彈來襲。由于該系統(tǒng)還在試用階段,所以只有一套系統(tǒng),因此有可能不能攔截所有的導(dǎo)彈。
輸入格式輸入數(shù)據(jù)為兩行,
第一行為導(dǎo)彈的數(shù)目N(n<=1000)
第二行導(dǎo)彈依次飛來的高度,所有高度值均為不大于30000的正整數(shù)。
輸出格式輸出只有一行是這套系統(tǒng)最多能攔截的導(dǎo)彈數(shù)和要攔截所有導(dǎo)彈最少要配備這種導(dǎo)彈攔截系統(tǒng)的套數(shù)。兩個數(shù)據(jù)之間用一個空格隔開.
樣例輸入
8
389 207 155 300 299 170 158 65
樣例輸出
6 2
轉(zhuǎn)載于:https://www.cnblogs.com/Keven02/p/6431343.html
總結(jié)
以上是生活随笔為你收集整理的最长下降/上升子序列问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lazy ideas in progra
- 下一篇: Google API 设计指南 - 前言