1. 程式人生 > >HDU 1257 最少攔截系統 LIS

HDU 1257 最少攔截系統 LIS

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

怎麼辦呢?多搞幾套系統唄!你說說倒蠻容易,成本呢?成本是個大問題啊.所以俺就到這裡來求救了,請幫助計算一下最少需要多少套攔截系統.

    求最長(嚴格)上升序列(Longest Increasing Subsequence)。這樣的長度才是 最少需要的 套數,因為這個序列中的任何兩個導彈都不能共用一個攔截系統 ,而且其餘的導彈 都能和這個最長序列中的某個導彈分為同一組。

   證明:對於數列中的一個最長(嚴格)上升序列,長度為k,其餘任何數都可以分在這個最長序列中,構成k組單調減序列:

               例如 a1 a2 a3 a4 a5 a6 a7 a8 a9 

               已經求得   a3       a5 a6     a8      為最長嚴格上升子序列(LSIS),且組成4個組。

               對於a9

                     a9 <= a8 ,否則a9屬於這個LSIS;所以,a9可以和a8分一組。

               對於a7

                    若a7 <= a6, 則a7可以和a6分一組;

                    若a7 > a6,

                                    a.  如果a7 >= a8,則a7可以和a8分一組;

                                    b. 如果a7 < a8, 則 a6 a7 a8 可替代a6 a8,構成LSIS,矛盾。

              對於a4,同a7

              對於a2,a2 >= a3,否則與LSIS矛盾。所以,a2與a3可分為一組。

              對於a1,

                   若a1 >= a2 可與a3同組

                   若a1 < a2,

                                   a.如果a1 >= a3,可以與a3分在一組

                                   b.如果a1 < a3, 則 a1 a3 可代替a3,與LSIS,矛盾。      

                同理可證任意n,k。

#include<stdio.h>
#define N 30001
int ary[N], dp[N];

int LIS(int *ary, int n)
{
	int i, j, m;
	dp[1] = 1;
	for(i = 2; i <= n; i++)
	{
		m = 0;
		for(j = 1; j < i; j++)
		{
			if(ary[i] > ary[j] && dp[j] > m)
			{
				m = dp[j];
			}
		}
		dp[i] = m + 1;
	}
	m = 0;
	for(i = 1; i <= n; i++)
	{	 
	  if(dp[i] > m)
		  m = dp[i];
	 }
	return m;
}
int main()
{
  int n, i, j, m;
  
  while(scanf("%d", &n) != EOF )
 {  
	  for(i = 1; i <= n; i++)
	  {
		scanf("%d", ary + i);
	  }  
	  
	  printf("%d\n", LIS(ary, n));
  }
}

參考: