[2010年NOIP普及组] 导弹拦截

思路:所有的导弹,不是被1号系统拦截就是被2号系统拦截,所以将导弹分成两部分(即被1号系统拦截的部分和被2号系统拦截的部分)进行枚举答案。因为根据题意,每个系统的半径即为该系统拦截的导弹中距离系统坐标最远的导弹的距离,所以不妨先算出每个导弹距离1号系统的距离,然后以距1号系统的距离进行升序排序。然后从距离1号系统最远的那枚导弹开始,计算出比它距离1号系统的距离远的所有导弹中距离2号系统的距离最远的那个距离(即以它前一枚导弹为1号系统所拦截的最远的导弹时,2号系统的半径),预处理结束后直接进行枚举答案,枚举1号系统所拦截的最远的导弹,然后输出最小的答案即可。 为了方便代码中所有距离直接用它的平方进行比较

代码:

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y;
}s1,s2,m[100005];
struct struct_node
{
int s1,s2;
}sum[100005];
int n;
int comp(struct_node a,struct_node b)
{
return a.s1<=b.s1;
}
int main()
{
cin >> s1.x >> s1.y >> s2.x >> s2.y;
cin >> n;
for (int i=1;i<=n;i++)
{
cin >> m[i].x >> m[i].y;
}
for (int i=1;i<=n;i++)
{
sum[i].s1=abs(m[i].x-s1.x)*abs(m[i].x-s1.x)+abs(m[i].y-s1.y)*abs(m[i].y-s1.y);
sum[i].s2=abs(m[i].x-s2.x)*abs(m[i].x-s2.x)+abs(m[i].y-s2.y)*abs(m[i].y-s2.y);
}
sort(sum+1,sum+n+1,comp);
int min=sum[n].s1,max=-1;
for (int i=n;i>=1;i--)
{
if (sum[i].s2>max)
{
max=sum[i].s2;
}
if (sum[i-1].s1+max<min)
{
min=sum[i-1].s1+max;
}
}
cout << min << endl;
return 0;
}