1. 程式人生 > >NYOJ 79 攔截導彈 (經典dp) 最長上升子序列 LIS

NYOJ 79 攔截導彈 (經典dp) 最長上升子序列 LIS

描述

某國為了防禦敵國的導彈襲擊,發展中一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於等於前一發的高度。某天,雷達捕捉到敵國導彈來襲。由於該系統還在試用階段,所以只用一套系統,因此有可能不能攔截所有的導彈。

輸入
第一行輸入測試資料組數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

為末元素的最長遞增子序列,等於以使f(j)最大的那個aj為末元素的遞增子序列最末再加上ai;如果這樣的元素不存在,那麼ai自身構成一個長度為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;
 }