拦截导弹=最小路径覆盖+DP+水
题目大意
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于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.