【Problem description】
经过11年的韬光养晦,某国研发出了一种新的导弹拦截系统,凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截。当工作半径为0 时,则能够拦截与它位置恰好相同的导弹。但该导弹拦截系统也存在这样的缺陷:每套系统每天只能设定一次工作半径。而当天的使用代价,就是所有系统工作半径的平方和。
某天,雷达捕捉到敌国的导弹来袭。由于该系统尚处于试验阶段,所以只有两套系统投入工作。如果现在的要求是拦截所有的导弹,请计算这一天的最小使用代价。
【Input format】
第一行包含4 个整数x1、y1、x2、y2,每两个整数之间用一个空格隔开,表示这两套导弹拦截系统的坐标分别为(x1, y1)、(x2, y2)。
第二行包含1 个整数N,表示有N 颗导弹。接下来N 行,每行两个整数x、y,中间用一个空格隔开,表示一颗导弹的坐标(x, y)。不同导弹的坐标可能相同。
【Output format】
输出只有一行,包含一个整数,即当天的最小使用代价。
提示
两个点(x1, y1)、(x2, y2)之间距离的平方是(x1- x2)^2+(y1-y2)^2。
两套系统工作半径r1、r2 的平方和,是指r1、r2 分别取平方后再求和,即r1^2+r2^2。
【Algorithm design】
Enumeration & sort
【Problem analysis】
O(n)
首先把每一个点到两个系统的距离平方算出来
按一般套路来
枚举系统1打哪几个 系统2打哪几个
这样的话每次要把系统1范围内距其最远的算出来
而且如果系统1范围内打到的导弹要求半径已经能打到系统2分配的任务
系统2就没必要打了
出现了冗余计算
这里可以直接结构体快排
把距系统1的距离排列
则每次只要算范围内最后一个的距离
前面的就都能打到
系统二一个一个收下即可
Cmp条件:
bool cmp(node p,node q)
{
if(p.d[0]!=q.d[0])return p.d[0]<q.d[0];
else if(p.d[1]!=q.d[1])return p.d[1]>q.d[1];
else return p.id<q.id;
}
因为发现距离系统1相等而位置不一的导弹到系统2的距离不等
所以优先把距系统2近的放在范围外
留给系统2收下
第一次TLE是每次都把系统2的范围枚举算一遍 其实是出现了冗余
每次只要把系统1扔出来的一个算入即可
第二次WA是距离的处理位置放错了导致意义不明
【Source code】
#include <bits/stdc++.h>
#define F(i,j,k) for(int i=j;i<=k;i++)
#define D(i,j,k) for(int i=j;i>=k;i--)
#define MAXN 99999999
using namespace std;
struct node
{
int rx,ry,d[2],id;
}rac[100001];//d[0],d[1]分别表示到系统1,2距离
int x[2],y[2],r[2];
int n,ans=MAXN;
int dis(int a,int b,int c,int d)
{
return (a-c)*(a-c)+(b-d)*(b-d);
}//距离公式
bool cmp(node p,node q)
{
if(p.d[0]!=q.d[0])return p.d[0]<q.d[0];
else if(p.d[1]!=q.d[1])return p.d[1]>q.d[1];
else return p.id<q.id;
}//前文提过了
void readp()
{
F(i,0,1)
cin>>x[i]>>y[i];
cin>>n;
F(i,1,n)
{
cin>>rac[i].rx>>rac[i].ry;
F(j,0,1)rac[i].d[j]=dis(rac[i].rx,rac[i].ry,x[j],y[j]);
rac[i].id=i;
}//储存距离
sort(rac+1,rac+n+1,cmp);//排序
return;
}
void work()
{
int cnt=0;
D(i,n,0)
{
if(i!=n)cnt=max(rac[i+1].d[1],cnt);
//一打不完所有的就要加上系统二
if(i!=0)cnt+=rac[i].d[0];
//二打不完所有的就算上一的最大值
ans=min(ans,cnt);
//打擂台取最小值
cnt-=rac[i].d[0];
//还原系统二半径平方
}
return;
}
void write()
{
cout<<ans<<endl;
return;
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
std::ios::sync_with_stdio(false);
readp();
work();
write();
return 0;
}
以上、