NYOJ 79 攔截導彈 (經典dp) 最長上升子序列 LIS
阿新 • • 發佈:2019-02-18
- 描述
-
某國為了防禦敵國的導彈襲擊,發展中一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於等於前一發的高度。某天,雷達捕捉到敵國導彈來襲。由於該系統還在試用階段,所以只用一套系統,因此有可能不能攔截所有的導彈。
- 輸入
- 第一行輸入測試資料組數N(1<=N<=10)
接下來一行輸入這組測試資料共有多少個導彈m(1<=m<=20)
接下來行輸入導彈依次飛來的高度,所有高度值均是大於0的正整數。 - 輸出
- 輸出最多能攔截的導彈數目
- 樣例輸入
-
2 8 389 207 155 300 299 170 158 65 3 88 34 65
- 樣例輸出
-
6 2
- 來源
- 上傳者
- 張潔烽
動態規劃法:O(n^2)
設f(i)表示L中以ai為末元素的最長遞增子序列的長度。則有如下的遞推方程:
f(i)=max(f(i+1),f(i+2),...,f(L-1),f(L))+1;用一個int dp[i]陣列儲存當前的f(i)值,可想而知最後 *max_element(dp,dp+L) 便得到了答案這個遞推方程的意思是,在求以ai為末元素的最長遞增子序列時,找到所有序號在L前面且小於ai的元素aj,即j<i且aj<ai。如果這樣的元素存在,那麼對所有aj,都有一個以aj為末元素的最長遞增子序列的長度f(j),把其中最大的f(j)選出來,那麼f(i)就等於最大的f(j)加上1,即以ai
模板如下:
#include<stdio.h> #include<stdlib.h> int main() { int n,m,i,j,max; int a[20],dp[20]; scanf("%d",&n); while(n--) { scanf("%d",&m); for(i=0;i<=m-1;i++) { scanf("%d",&a[i]); dp[i]=1; //dp[i]的最小值為1 } for(i=m-2;i>=0;i--) { for(j=i+1;j<=m-1;j++) { if((a[j]<a[i])&&(dp[i]<dp[j]+1)) //最長遞減子序列則a[j]<a[i],而最長遞增子序列則a[j]>a[i]。。。。好好體會。。。。 { dp[i]=dp[j]+1; //更新dp[i] } } } max=dp[0]; for(i=0;i<=m-1;i++) { if(max<dp[i]) max=dp[i]; } printf("%d\n",max); } system("pause"); return 0; }