洛谷1020 导弹拦截 解题报告

洛谷1020 导弹拦截

本题地址: http://www.luogu.org/problem/show?pid=1020

题目描述

  某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
   
  输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出格式

输入格式:

一行,若干个正整数。

输出格式:

2行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入输出样例

输入样例#1:

389 207 155 300 299 170 158 65

输出样例#1:

6
2

题解

经过分析,我们容易发现其本质就是寻找导弹高度的最长上升子序列(LIS)。

我们可以定义f[i]表示从前往后,以h[i]为最后一个元素的最长上升子序列的长度,需要在(1<=j<=i-1 且 h[j]<h[i])的f[j]中取最优值来求解f[i]。

所以可以枚举前i-1个状态进行状态转移,得出方程:

f[i]:=max{f[j]}+1    (1<=j<=i-1 且 h[j]<h[i])

ans=max{f[i]}    (1<=i<=n)

时间复杂度为O(n^2)。

下面附上代码。

代码

  1. var    
  2.   n,i,j,max:longint;    
  3.   a,b:array[1..1000] of integer;    
  4. begin    
  5. while not eoln do    
  6.     begin    
  7.      inc(n);    
  8.      read(a[n]);    
  9.       end;    
  10.   for i:=to n do    
  11.    b[i]:=1;    
  12.   max:=0;    
  13.   for i:=to n-do    
  14.    for j:=i+to n do    
  15.     if (a[j]<a[i])and(b[j]<1+b[i]) then b[j]:=1+b[i];    
  16.   for i:=to n do    
  17.    if b[i]>max then max:=b[i];    
  18.   writeln(max);    
  19.   for i:=to n do    
  20.    b[i]:=1;    
  21.   max:=0;    
  22.   for i:=to n-do    
  23.    for j:=i+to n do    
  24.     if (a[j]>a[i])and(b[j]<1+b[i]) then b[j]:=1+b[i];    
  25.   for i:=to n do    
  26.    if b[i]>max then max:=b[i];    
  27.   writeln(max);    
  28.   readln;    
  29.   readln;    
  30. end.   

(本文系笔者原创,未经允许不得转载)

原文地址:https://www.cnblogs.com/yzm10/p/4752912.html