ACM-ICPC 2018 沈阳赛区网络预赛 E. The cake is a lie(最小圆覆盖)
解析:
最小圆覆盖模板+二分答案
∠1是phi
∠2是theta
按逆时针来算角度的
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define Mn 300
const double eps = 1e-9;
const double pi = acos(-1.0);
#define sqr(x) ((x) * (x))
struct point
{
double x,y;
void read()
{
scanf("%lf%lf",&x,&y);
}
void print()
{
printf("%lf%lf\n",x,y);
}
double friend dis(const point &a,const point &b)
{
return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}
} p[Mn + 5];
struct alpha
{
double v;
bool flag;
bool friend operator <(const alpha &a,const alpha &b)
{
return a.v < b.v;
}
} alp[Mn * Mn + 5];
int solve(int n,double R)//半径为R的圆最多能覆盖多少个点
{
int MAX = 0;
for(int i = 0; i < n; i++)
{
int t = 0;
for(int j = 0; j < n; j++)
{
if(i == j)
continue;
double theta,phi,D;
D = dis(p[i],p[j]);
if(D > 2.0 * R)
continue;
theta = atan2(p[j].y - p[i].y,p[j].x - p[i].x);
if(theta < 0)
theta += 2 * pi;
phi = acos(D / (2.0 * R));
alp[t].v = theta - phi + 2 * pi;
alp[t].flag = true;
alp[t + 1].v = theta + phi + 2 * pi;
alp[t + 1].flag = false;
t += 2;
}
sort(alp,alp + t);
int sum = 0;
for(int j = 0; j < t; j++)
{
if(alp[j].flag)
sum ++;
else
sum --;
if(sum > MAX)
MAX = sum;
}
}
return MAX+1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,s;
int R;
scanf("%d%d",&n,&s);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
scanf("%d",&R);
double l=0;
double r=30000;
double ans=0;
while(r-l>eps)
{
double mid=(l+r)/2;
if(solve(n,mid)>=s) ans=mid,r=mid;
else l=mid+0.00001;
}
if(ans==0) printf("The cake is a lie.\n");
else printf("%.4lf\n",(double )ans+R);
}
return 0;
}