2018.12.30【NOIP提高组】模拟A组 JZOJ 5354 导弹拦截

版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/85382432

大意

三维导弹拦截


思路

对于最多干掉的导弹数,由于导弹同时发射的,所以我们可以排序,然后 O ( n 2 ) O(n^2) L I S LIS 即可

对于最少系统数,用类似导弹拦截第二问匹配解法的方法求最小路径覆盖即可


代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 2000001
#define LL long long
#define r(i,a,b) for(int i=a;i<=b;i++)
#define zero(a) memset(a,0,sizeof(a))
using namespace std;int n,f[1001],ans1,ans2;
struct node{int next,to;}edge[M];int l[M],tot,x,y,link[1001],ans,t;bool vis[1001];
void add(int u,int v){edge[++tot].to=v;edge[tot].next=l[u];l[u]=tot;}
struct nxde{int x,y,z;}a[1001];
inline bool cmp(nxde x,nxde y){return x.x<y.x;}
bool operator <(nxde x,nxde y){return x.x<y.x&&x.y<y.y&&x.z<y.z;}//定义新的比较规则
LL read()
{
    char c;int f=0,d=1;
    while((c=getchar())<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48;
    while((c=getchar())>=48&&c<=57)f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
bool find(int p)
{
    for(int i=l[p];i;i=edge[i].next)
     if(!vis[edge[i].to])
      {
      	vis[edge[i].to]=1;
      	int q=link[edge[i].to];
      	link[edge[i].to]=p;
      	if(!q||find(q)) return true;
      	link[edge[i].to]=q;
      }
    return false;
}
int main()
{
	freopen("missile.in","r",stdin);
	freopen("missile.out","w",stdout);
	scanf("%d",&n);
	for(register int i=1;i<=n;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),f[i]=1;
	sort(a+1,a+1+n,cmp);//记得要排序,否则30
	for(register int i=1;i<=n;i++)
	{
		for(register int j=1;j<i;j++)if(a[j]<a[i])f[i]=max(f[i],f[j]+1),add(i,j);
		ans1=max(ans1,f[i]);//暴力转移
	}
    printf("%d\n",ans1);
    r(i,1,n)
    {
        zero(vis);
        ans2+=find(i);//加上是否可以匹配
    }
    printf("%d",n-ans2);//最少系统数=总个数-最大匹配数
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/85382432