Description
给出圆心o的坐标和n个点的坐标,问以o为圆心且覆盖这n个点的圆环的最小面积
Input
第一行三个整数n,x,y分别表示点数和圆心o的坐标,之后n行每行两个整数xi,yi表示该点坐标,以顺时针或者逆时针顺序输入,且保证不存在三点共线的情况
(3<=n<=100000,-10^6<=xi,yi<=10^6)
Output
输出以o为圆心且覆盖这n个点的圆环的最小面积
Sample Input
3 0 0
0 1
-1 2
1 2
Sample Output
12.566370614359172464
Solution
问题转化为o点到n个点的最远距离以及o点到n个线段的最近距离
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 111111
#define INF 0x7f7f7f7f7f
#define PI acos(-1.0)
struct node
{
double x,y;
}o,p[maxn];
int n;
double dis(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double get_dis(node a,node b,node c)
{
double A=dis(b,c),B=dis(a,c),C=dis(a,b);
if(A*A+C*C<=B*B)return A;
if(B*B+C*C<=A*A)return B;
double s=abs((a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x));
return s/dis(a,b);
}
int main()
{
while(~scanf("%d%lf%lf",&n,&o.x,&o.y))
{
double Min=INF,Max=0;
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
double temp=dis(p[i],o);
Max=max(Max,temp);
}
for(int i=0;i<n;i++)
{
int j=(i+1)%n;
Min=min(Min,get_dis(p[i],p[j],o));
}
printf("%.10lf\n",(Max*Max-Min*Min)*PI);
}
return 0;
}