http://codeforces.com/contest/614/problem/C
给出一个n边形,求把多边形 通过一条线,绑在一个点上,绕这个点旋转,所扫过的面积。 (P点一定在多边形外部)
给出n个点端点;
直接求出离P最远的一个点,这个点到P的距离就是多边形能扫过的最大圆的半径(外圆)
然后求多边形的n-1条边(注意,是线段,不是直线) 到 p点的距离,取最短的,就是 多边形扫过的 最短半径(内圆)
pi*(max*max-min*min)就是答案
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
double min(double a, double b)
{return a<b?a:b;}
struct POINT
{
double x;
double y;
POINT(double a=0, double b=0) { x=a; y=b;}
};
struct LINESEG
{
POINT s;
POINT e;
LINESEG(POINT a, POINT b) { s=a; e=b;}
LINESEG() { }
};
__int64 n,m;
const double pi=acos(-1.0);
double dist(POINT p1,POINT p2) //2点距离
{
return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );
}
double dotmultiply(POINT p1,POINT p2,POINT p0) //
{
return ((p1.x-p0.x)*(p2.x-p0.x) + (p1.y-p0.y)*(p2.y-p0.y));
}
double relation(POINT c,LINESEG l) //点线关系
{
LINESEG tl;
tl.s=l.s;
tl.e=c;
return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.e)*dist(l.s,l.e));
}
POINT perpendicular(POINT p,LINESEG l)
{
double r=relation(p,l);
POINT tp;
tp.x=l.s.x+r*(l.e.x-l.s.x);
tp.y=l.s.y+r*(l.e.y-l.s.y);
return tp;
}
double ptolinesegdist(POINT p,LINESEG l,POINT &np)//求点p到线段的最近点
{
double r=relation(p,l);
if(r<0)
{
np=l.s;
return dist(p,l.s);
}
if(r>1)
{
np=l.e;
return dist(p,l.e);
}
np=perpendicular(p,l);
return dist(p,np);
}
POINT tm[100005];
int main()
{
__int64 x,y;
int i,j;
__int64 px,py;
scanf("%I64d%I64d%I64d",&n,&px,&py);
double minn= 10000000000000000 ;
double maxx=0;
for (i=1;i<=n;i++)
{
scanf("%I64d%I64d",&x,&y);
x-=px;
y-=py;
tm[i]=POINT(x,y);
double tmp=x*x+y*y;
if (tmp>maxx)
maxx=tmp;
}
tm[n+1]=tm[1];
POINT p0(0,0);
POINT closed;
for (i=1;i<=n;i++)
{
LINESEG s1(tm[i],tm[i+1]);
closed=ptolinesegdist(p0,s1,closed);
double tmp_min=dist(closed,p0);
minn=min(minn,tmp_min*tmp_min);
}
printf("%.7lf\n",pi*(maxx-minn));
return 0;
}