1. 程式人生 > >2018.12.30【NOIP提高組】模擬A組 JZOJ 5354 導彈攔截

2018.12.30【NOIP提高組】模擬A組 JZOJ 5354 導彈攔截

大意

三維導彈攔截


思路

對於最多幹掉的導彈數,由於導彈同時發射的,所以我們可以排序,然後 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);//最少系統數=總個數-最大匹配數 }