题目大意
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
分析
第一问水dp
第二问就是因为每次只能击落比上一次更低的导弹,因此找到每一发导弹可以击落的其他导弹连边,然后就是最小路径覆盖。
代码
type
arr=record
x,y,w:longint;
next:longint;
end;
var
a:array[1..10000] of arr;
a1:array[0..12000] of longint;
v:array[1..30000] of boolean;
st,ls:array[1..30000] of longint;
i,j:longint;
n,m,nm:longint;
k:char;
t,t1:longint;
function find(r:longint):boolean;
var
i,j,k:longint;
begin
find:=true;
i:=ls[r];
while i<>0 do
begin
with a[i] do
if not v[y]
then
begin
k:=st[y]; st[y]:=r; v[y]:=true;
if (k=0) or find(k) then exit;
st[y]:=k;
end;
i:=a[i].next;
end;
find:=false;
end;
procedure main;
var
i,j,k:longint;
z:boolean;
begin
for i:=1 to n do
begin
fillchar(v,sizeof(v),0);
z:=find(i);
end;
end;
procedure main1;
var
a,b,c,d:array[0..12000] of longint;
i,j,k,s,num:longint;
begin
n:=0;
while not eoln do
begin
n:=n+1;
read(a[n]);
b[n]:=1;
end;
for i:=n-1 downto 1 do
begin
for j:=i+1 to n do
if (a[j]<=a[i])and(b[i]<b[j]+1)
then
begin
b[i]:=b[j]+1;
c[i]:=j;
end;
end;
k:=0;
for i:=1 to n do
if k<=b[i] then
k:=b[i];
writeln(k);
a1:=a;
end;
begin
main1;
fillchar(st,sizeof(st),0);
fillchar(ls,sizeof(ls),0);
for i:=1 to n-1 do
begin
for j:=i+1 to n do
if a1[i]>=a1[j] then begin
nm:=nm+1;
with a[nm] do
begin
x:=i;
y:=j;
next:=ls[x];
ls[x]:=nm;
end;
end;
end;
main;
j:=0;
for i:=1 to n do
if st[i]<>0 then j:=j+1;
writeln(n-j);
end.