Codeforces Peter 614 C and Snow Blower

传送门:http://codeforces.com/contest/613/problem/A
计算几何:
计算一个多边形绕着圆心旋转一周所得区域的面积,通过样例就可以看出应该是是一个圆环,所以只需要找到图形上到圆心的最远点和最近点即可,最远点一定在点上,最近点可能在点上可能在边上,具体判断方法是:由于点的给出方法为顺时针或逆时针,所以只需要O(n)扫一遍环即可,利用余弦定理去判断形成的角是否为钝角,(即最近点是不是在给定的边上)如果是钝角的话那么则取两个端点的最小值,如果不是的话则利用海伦公式求高即可,海伦公式是求面积的,导出高,再设置一下精度就ok了!!

#include 
using namespace std;
#define PI acos(-1)
struct Node{
    double x, y;
}node[100010];
double DISTANCE(int a, int b){
    return sqrt((node[a].x - node[b].x) * (node[a].x - node[b].x)
                + (node[a].y - node[b].y) * (node[a].y - node[b].y));
}
int main()
{
    int n;
    double up, down, s;
    scanf("%d%lf%lf", &n, &node[0].x, &node[0].y);
    up = 0; down = 1e20;
    for(int i = 1; i <= n; i++){
        scanf("%lf%lf", &node[i].x, &node[i].y);
        up = max(DISTANCE(i, 0), up);
    }
    for(int i = 1; i < n; i++){
        double a = DISTANCE(0, i);
        double b = DISTANCE(0, i + 1);
        double c = DISTANCE(i, i + 1);
        if(a*a + c*c - b*b < 0 ||  b*b + c*c - a*a < 0){
            down = min(down, min(a, b));
        }
        else{
            double p = (a + b + c) / 2;
            down = min(down, 2 * sqrt(p * (p - a) * (p - b) * (p - c)) / c);
        }    
    }
    {
        double a = DISTANCE(0, 1);
        double b = DISTANCE(0, n);
        double c = DISTANCE(1, n);
        if(a*a + c*c - b*b < 0 ||  b*b + c*c - a*a < 0){
            down = min(down, min(a, b));
        }
        else{
            double p = (a + b + c) / 2;
            down = min(down, 2 * sqrt(p * (p - a) * (p - b) * (p - c)) / c);
        }
    }
    s = ((up * up) - (down * down)) * PI;
    printf("%.16lf\n", s);
    return 0;
}

你可能感兴趣的:(ACM)