洛谷的题。。。在此省略题目。。。这题还是比较水的。。。
开始想用前缀s1和与后缀s2和做。。。后来发现是不是。。。没办法还是自己太菜了。。。
其实这道题很简单。。。就是给两个点,然后一系列的点,问以这两个点为圆心的半径平方后之和最小是多少。。。我们可以用结构体排序做。。。用一个结构体数组a[i].s1和a[i].s2如下:
struct dr{
int x,y,s1,s2;
}a[100050];
a[i].s1和a[i].s2表示i点到s1和s2的距离
然后再结构体按照a[i].s1降序排序就好了,这样排序处来,是以a[i].s1降序排序的,那么从1->n中间i数的含义是,前面的i-1个点是用第二个点打,而i->n由于降序排序,第一个点打到第i个点,那么后面都能被打到,而前1到i-1个点,需要求一个a[i].s2最大值然后与a[i].s1加起来。这样的意思是我第一点最远打到i点。这样从1-n+1扫一遍即可。。。n+1表示。。。第一个点压根不打。。。
最后注意初始化。。。以及结构排序需要写一个结构体排序的cmp函数
bool cmp(dr a,dr b){
return a.s1 > b.s1;
}
最后AC代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct dr{
int x,y,s1,s2;
}a[100050];
bool cmp(dr a,dr b){
return a.s1 > b.s1;
}
int main(){
int n,x1,x2,y1,y2;
while (~scanf("%d%d%d%d",&x1,&y1,&x2,&y2)){
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
a[i].s1=(a[i].x-x1)*(a[i].x-x1)+(a[i].y-y1)*(a[i].y-y1);
a[i].s2=(a[i].x-x2)*(a[i].x-x2)+(a[i].y-y2)*(a[i].y-y2);
}
sort(a+1,a+1+n,cmp);
a[0].s2=0;
a[n+1].s1=0;
int r=0;
int ans=1000000000;
for (int i=1;i<=n+1;i++){
r=max(r,a[i-1].s2);
ans=min(ans,a[i].s1+r);
}
printf("%d\n",ans);
}
return 0;
}