1. 程式人生 > >動態規劃之最長遞增子序列(LIS)

動態規劃之最長遞增子序列(LIS)

lib sca while -c -o 組成 describe log ret

在一個已知的序列{ a1,a2,……am}中,取出若幹數組成新的序列{ ai1, ai2,…… aim},其中下標 i1,i2, ……im保持遞增,即新數列中的各個數之間依舊保持原數列中的先後順序,那麽稱{ ai1, ai2,……aim}為原序列的一個子序列。若在子序列中,當下標 ix > iy時,aix > aiy,那麽稱其為原序列的一個遞增子序列。最長遞增子序列問題就是在一個給定的原序列中,求得其最長遞增子序列的長度。

求最長遞增子序列的遞推公式為:

F(1) = 1;

F(i) = max{ 1, F[j]+1 | aj<ai && j<i}

攔截導彈

題目描述

某國為了防禦敵國的導彈襲擊,開發出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的導彈來襲,並觀測到導彈依次飛來的高度,請計算這套系統最多能攔截多少導彈。攔截來襲導彈時,必須按來襲導彈襲擊的時間順序,不允許先攔截後面的導彈,再攔截前面的導彈。

輸入描述:

每組輸入有兩行,
第一行,輸入雷達捕捉到的敵國導彈的數量k(k<=25),
第二行,輸入k個正整數,表示k枚導彈的高度,按來襲導彈的襲擊時間順序給出,以空格分隔。

輸出描述:

每組輸出只有一行,包含一個整數,表示最多能攔截多少枚導彈。
示例1

輸入

8
300 207 155 300 299 170 158 65

輸出

6

解題思路:要求最多能攔截多少枚導彈,即在按照襲擊順序排列的導彈高度中求其最長不增子序列。其中

F(1) = 1;

F(i) = max{ 1, F[j]+1 | aj>=ai && j<i}

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 int list[26];  //按順序保存導彈高度
5 int dp[26]; //保存以第i個導彈結尾的最長不增長序列長度 6 int max( int a,int b) 7 { 8 //選取最大值 9 return a>b? a:b; 10 } 11 int main() 12 { 13 int n; 14 int tmax,ans; 15 int i,j; 16 while( scanf("%d",&n)!=EOF) 17 { 18 for( i=1; i<=n; i++) 19 { 20 scanf("%d",&list[i]); 21 dp[i] = 0; 22 } 23 for( i=1; i<=n; i++) 24 { 25 tmax = 1; //最長不增長子序列長度至少為1 26 for( j=1; j<i; j++) //遍歷其前所有導彈高度 27 { 28 if( list[j]>=list[i]) //若j號導彈不比當前導彈低 29 { 30 tmax = max( tmax,dp[j]+1); 31 } 32 } 33 dp[i] = tmax; 34 } 35 ans = 1; 36 for( i=1; i<=n; i++) 37 ans = max( ans, dp[i]); 38 printf("%d\n",ans); 39 } 40 41 return 0; 42 }

動態規劃之最長遞增子序列(LIS)