题目链接:http://codeforces.com/problemset/problem/614/C
题目大意:
下雪了,于是小明买了个多边形的扫雪器,多边形只能围绕一个点做圆周运动,那么给出这个点,以及顺时针给出多边形的各个点求这个多变形做圆周运动扫过的面积。
思路:
样例已经给了很清楚的解释。所能扫到最远的距离的一定是多边形的某个顶点,所以最远的确定下来了。接下来是内圈能到的最近,也就是点到每根线段的最短距离中最短的。
所以问题就是求 1.距离定点最远的点的距离MAX 2.距离定点最近的线段的距离(点到每条线段的最短距离)MIN
ans=M_PI*(MAX-MIN) 注意:由于本题的距离只需要定性比较长短即可,所以本题的MAX,MIN都是距离的平方,以便随后计算圆的面积。
MAX很好求,问题就在于MIN。于是枚举每一根线段求点到直线最短距离。以下是点到线段距离的向量求法:
当<0时,return dis(P,A);
当>1时,return dis(P,B);
(0,1)时 return dis(P,C); C点可由求出,具体看代码(写的比较丑,读者懂意思就行)
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
using namespace std;
struct Point
{
double x,y,dis;
}C[1000005];
double c_x,c_y;
int n;
const double M_P=3.1415926535897932384626433;
double dis(double x,double y){
return (x-c_x)*(x-c_x)+(y-c_y)*(y-c_y);
}
double dis2(Point a,Point b)
{
Point A=a,B=b;
Point AB,OA;
AB.x=B.x-A.x;
AB.y=B.y-A.y;
OA.x=A.x-c_x;
OA.y=A.y-c_y;
double ye=-(AB.x*OA.x+AB.y*OA.y)/(AB.x*AB.x+AB.y*AB.y);
if(ye<0||ye>1)return 1e18;
Point AN;
AN.x=ye*AB.x;AN.y=ye*AB.y;
Point N;
N.x=AN.x+A.x;N.y=AN.y+A.y;
return dis(N.x,N.y);
}
int main()
{
cin>>n>>c_x>>c_y;
double MAX=0;double Min=1e18;
for(int i=0;i<n;i++)
{
double a,b;cin>>a>>b;
if(MAX<dis(a,b))MAX=dis(a,b);
if(Min>dis(a,b))Min=dis(a,b);
C[i].x=a;C[i].y=b;C[i].dis=dis(a,b);
}
//cout<<Min<<endl;
for(int i=0;i<n;i++)
{
if(Min>dis2(C[i],C[(i+1)%n]))Min=dis2(C[i],C[(i+1)%n]);
// cout<<Min<<endl;
}
printf("%.18lf\n",M_P*(MAX-Min));
}