5354. 【NOIP2017提高A组模拟9.9】导弹拦截

it2023-01-19  60

Description

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。 敌国的导弹形成了立体打击,每个导弹可以抽象成一个三维空间中的点(x; y; z)。拦截系统发射的炮弹也很好地应对了这种情况,每一发炮弹也可以视为一个三维空间中的点。 但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达三维空间中任意的点,但是以后每一发炮弹到达点的坐标(x; y; z) 的三个坐标值都必须大于前一发炮弹的对应坐标值。 某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。 输入导弹飞来的坐标,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。注意: 所有导弹都是同时飞来的。

Input

第一行一个正整数n,表示敌国导弹数目。 接下来n 行,每行三个非负整数xi,yi,zi,表示一个敌国导弹的三维坐标。 数据保证所有的导弹坐标互不相同。

Output

第一行一个整数,表示一套系统最多拦截的导弹数。 第二行一个整数,表示拦截所有导弹最少配备的系统数。

Sample Input

4 0 0 0 1 1 0 1 1 1 2 2 2

Sample Output

3 2

Data Constraint

对于30% 的数据,n <=10 对于100% 的数据,n <= 1000,x; y; z <= 10^6

Solution

第一问是一个最长不下降子序列,n^2 dp,第二问是最小链覆盖,用匈牙利算法。

Code

#include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define I int #define ll long long #define F(i,a,b) for(I i=a;i<=b;i++) #define Fd(i,a,b) for(I i=a;i>=b;i--) #define mem(a,b) memset(a,b,sizeof a) #define N 1002 using namespace std; void R(I &x){ I w=1;x=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} x*=w; } I n,f[N],m[N*2],bz[N*2],ans,cnt; I t[N*N],nx[N*N],ls[N<<1],tot; struct node{I x,y,z;}a[N]; I dfs(I x){ for(I k=ls[x];k;k=nx[k]){ if(bz[t[k]]) continue; bz[t[k]]=1; if(m[t[k]]==-1||dfs(m[t[k]])){ m[t[k]]=x; return 1; } } return 0; } I cmp(node x,node y){return x.x<y.x;} void add(I x,I y){ t[++tot]=y,nx[tot]=ls[x],ls[x]=tot; } I main(){ freopen("missile.in","r",stdin); freopen("missile.out","w",stdout); R(n); F(i,1,n) R(a[i].x),R(a[i].y),R(a[i].z); sort(a+1,a+1+n,cmp); a[0]=node{-1,-1,-1}; F(i,1,n){ F(j,0,i-1) if(a[i].x>a[j].x&&a[i].y>a[j].y&&a[i].z>a[j].z) f[i]=max(f[i],f[j]+1); ans=max(ans,f[i]); } printf("%d\n",ans); F(i,1,n){ F(j,1,i-1) if(i!=j&&a[i].x>a[j].x&&a[i].y>a[j].y&&a[i].z>a[j].z) add(j,n+i); } mem(m,255); F(i,1,n){ mem(bz,0); cnt+=dfs(i); } printf("%d\n",n-cnt); return 0; }

 

最新回复(0)