http://codeforces.com/contest/617/problem/C
题意:给你n个点,2个圆心,
让你选择半径r1,r2使得两个圆能完整覆盖所有点,并且要求 r1*r1+r2*r2最小
思路:
val1 : 点x到圆心1的距离
val2:点x到圆心2的距离
先把n个点 放入一个 按照 val2排序递减的set
把n个点按val1递增排序
按val1值从小到大遍历
{
从set里去掉点x,
设圆1的半径为 dis(点x到r1)也即val1;
那么x之前的点 肯定都被 圆1覆盖了,其余没被覆盖的点都在set里面,那么取set的第一个点的val2值作为圆2半径,就可保证2圆覆盖所有点
更新ans=min(ans,r1*r1+r2*r2);
}
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <iostream>
using namespace std;
double eps=0.000001;
struct node
{
__int64 x,y;
__int64 val1;
__int64 val2;
bool operator ==(const node& b)const
{
return x==b.x&&y==b.y;
}
bool operator <(const node& b)const
{
return val2>b.val2;
}
};
node tm1[2005];
__int64 cmp1(node &a,node&b)
{return a.val1<b.val1;}
set<node> sb;
int main()
{
__int64 n,i;
__int64 x1,x2,y2,y1;
scanf("%I64d",&n);
scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);
for (i=1;i<=n;i++)
{
scanf("%I64d %I64d",&tm1[i].x,&tm1[i].y);
tm1[i].val1=(tm1[i].x-x1)*(tm1[i].x-x1)+(tm1[i].y-y1)*(tm1[i].y-y1);
tm1[i].val2=(tm1[i].x-x2)*(tm1[i].x-x2)+(tm1[i].y-y2)*(tm1[i].y-y2);
sb.insert(tm1[i]);
}
sort(tm1+1,tm1+n+1,cmp1);
set<node>::iterator it;
it=sb.begin();
__int64 dis1= it->val2;
__int64 ans=dis1;
for (i=1;i<=n;i++)
{
sb.erase(tm1[i]);
__int64 dis1=0;
if(!sb.empty())
{
it=sb.begin();
dis1= it->val2;
}
__int64 tmp_ans=tm1[i].val1+dis1;
if (tmp_ans<ans) ans=tmp_ans;
}
printf ("%I64d\n",ans);
return 0;
}