题解 P1158 【导弹拦截】
难度,还可以吧,想出来了就不难了。。。
关键是贪心的思路与后缀和数组,底下代码里写得很详细
附:这是我第一次写题解。。。
/* AKBOY原创
先按照每个顶点到拦截器1的距离排序
(后面的下标按排过序后的为准)
枚举拦截器1的范围 拦截器2就确定了
(边缘必定覆盖一个顶点)
[用后缀和数组 来计算剩余的顶点中与
拦截器2最远的一个 (1~i由于距离都小于
或等于i到拦截器1的距离,必已被拦截器1
覆盖,此时算出i~n中离拦截器2最远的一
个就是拦截器2的半径。。。。。。) ]
由于计算的是平方和,就不需要+sqrt了,
免得麻烦得要死。。。。。。。。。。
*/
#include<cstdio>
#define N 100233
#include<algorithm>
using namespace std;
int n,ans,last[N];
struct Node
{
int x,y;
}t1,t2,s[N];
inline int Squ(int v);
inline int Dist(Node u,Node v);
bool Cmp(Node p,Node q)
{
return Dist(t1,p)<Dist(t1,q);
}
int main(void)
{
freopen("P1158.in","r",stdin);
freopen("P1158.out","w",stdout);
scanf("%d%d%d%d",&t1.x,&t1.y,&t2.x,&t2.y);
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d%d",&s[i].x,&s[i].y);
sort(s+1,s+1+n,Cmp);
for(int i=n;i>=1;--i)/*后缀和数组的应用,计算第**i~n**个*/
last[i]=max(last[i+1],Dist(t2,s[i]));
ans=0x7fffffff;
for(int i=1;i<=n;++i)
ans=min(ans,Dist(t1,s[i])+last[i+1]);
printf("%d\n",ans);
return 0;
}
inline int Squ(int v)
{
return v*v;
}
inline int Dist(Node u,Node v)
{
return Squ(u.x-v.x)+Squ(u.y-v.y);
}