欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HDU - 5130 Signal Interference(计算几何—圆与多边形的面积交)

程序员文章站 2022-04-01 15:51:16
...

Signal Interference

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 2500    Accepted Submission(s): 1260
Special Judge

Problem Description

Two countries A-Land and B-Land are at war. The territory of A-Land is a simple polygon with no more than 500 vertices. For military use, A-Land constructed a radio tower (also written as A), and it's so powerful that the whole country was under its signal. To interfere A-Land's communication, B-Land decided to build another radio tower (also written as B). According to an accurate estimation, for any point P, if the euclidean distance between P and B is no more than k (0.2 ≤ k < 0.8) times of the distance between P and A, then point P is not able to receive clear signals from A, i.e. be interfered. Your task is to calculate the area in A-Land's territory that are under B-Land's interference.

 Input

There are no more than 100 test cases in the input.

In each test case, firstly you are given a positive integer N indicating the amount of vertices on A-Land's territory, and an above mentioned real number k, which is rounded to 4 digits after the decimal point. 

Then N lines follow. Each line contains two integers x and y (|x|, |y| ≤ 1000), indicating a vertex's coordinate on A's territory, in counterclockwise or clockwise order. 

The last two lines of a test case give radio tower A and B's coordinates in the same form as vertexes' coordinates. You can assume that A is not equal to B.

 Output

For each test case, firstly output the case number, then output your answer in one line following the format shown in sample. Please note that there is a blank after the ':'.

Your solution will be accepted if its absolute error or relative error is no more than 10-6.

This problem is special judged.

 Sample Input

4 0.5000 -1 -1 1 -1 1 1 -1 1 0 0 -1 0

 Sample Output

Case 1: 0.2729710441

 Source

2014ACM/ICPC亚洲区广州站-重现赛(感谢华工和北大)

根据PA=kPB,得到(x-x1)^2+(y-y1)^2=k^2(x-x2)^2+k^2(y-y2)^2,将这个等式化简正好是圆的一般方程,然后就是圆与多边形的面积交模板了

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const int inf = 1e20;
const int maxp = 1005;
const double pi = acos(-1.0);
int sgn(double x)
{
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    else return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y)
    {
        x = _x;
        y = _y;
    }
    void input()
    {
        scanf("%lf %lf",&x,&y);
    }
    Point operator + (const Point &b) const
    {
        return Point(x + b.x,y + b.y);
    }
    Point operator - (const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }
    double operator ^ (const Point &b) const
    {
        return x * b.y - y * b.x;
    }
    double operator * (const Point &b) const
    {
        return x * b.x + y * b.y;
    }
    Point operator * (const double &k) const
    {
        return Point(x * k, y * k);
    }
    double distance(Point p)
    {
        return hypot(x - p.x,y - p.y);
    }
    double rad(Point a,Point b)
    {
        Point p = *this;
        return fabs(atan2( fabs((a - p) ^ (b - p)),(a - p) * (b - p) ) );
    }
    Point operator / (const double &k) const
    {
        return Point(x / k, y / k);
    }
    double len()
    {
        return hypot(x,y);
    }
    double len2()
    {
        return x * x + y * y;
    }
    Point trunc(double r)
    {
        double l = len();
        if(!sgn(l)) return *this;
        r /= l;
        return Point(x * r,y * r);
    }
};
struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;
        e = _e;
    }
    double length()
    {
        return s.distance(e);
    }
    double dispointtoline(Point p)
    {
        return fabs( (p - s) ^ (e - s)) / length();
    }
    Point lineprog(Point p)
    {
        return s + ( ((e - s) * ((e - s) * (p - s))) / ((e - s).len2()) );
    }
};
struct circle
{
    Point p;
    double r;
    circle(){}
    circle(double x,double y,double _r)
    {
        p = Point(x,y);
        r = _r;
    }
    int relation(Point b)
    {
        double dst = b.distance(p);
        if(sgn(dst - r) < 0) return 2;
        else if(sgn(dst - r) == 0) return 1;
        else return 0;
    }
    int relationline(Line v)
    {
        double dst = v.dispointtoline(p);
        if(sgn(dst - r) < 0) return 2;
        else if(sgn(dst - r) == 0) return 1;
        return 0;
    }
    int pointcrossline(Line v,Point &p1,Point &p2)
    {
        if(!(*this).relationline(v)) return 0;
        Point a = v.lineprog(p);
        double d = v.dispointtoline(p);
        d = sqrt(r * r - d * d);
        if(sgn(d) == 0) {
            p1 = a;
            p2 = a;
            return 1;
        }
        p1 = a + (v.e - v.s).trunc(d);
        p2 = a - (v.e - v.s).trunc(d);
        return 2;
    }
    double areatriangle(Point a,Point b)
    {
        if( sgn( (p - a) ^ (p - b)) == 0) return 0.0;
        Point q[5];
        int len = 0;
        q[len++] = a;
        Line l(a,b);
        Point p1,p2;
        if(pointcrossline(l,q[1],q[2]) == 2) {
            if(sgn((a - q[1]) * (b - q[1])) < 0) q[len++] = q[1];
            if(sgn((a - q[2]) * (b - q[2])) < 0) q[len++] = q[2];
        }
        q[len++] = b;
        if(len == 4 && sgn((q[0] - q[1]) * (q[2] - q[1])) > 0) swap(q[1],q[2]);
        double res = 0;
        for(int i = 0; i < len - 1; i++) {
            if(relation(q[i]) == 0 || relation(q[i + 1]) == 0) {
                double arg = p.rad(q[i],q[i + 1]);
                res += r * r * arg / 2.0;
            }
            else {
                res += fabs((q[i] - p) ^ (q[i + 1] - p)) / 2.0;
            }
        }
        return res;
    }
};
struct polygon
{
    int n;
    Point p[maxp];
    void input(int _n)
    {
        n = _n;
        for(int i = 0; i < n; i++) {
            p[i].input();
        }
    }
    double areacircle(circle c)
    {
        double ans = 0.0;
        for(int i = 0; i < n; i++) {
            int j = (i + 1) % n;
            if(sgn ( (p[j] - c.p ) ^ (p[i] - c.p ) ) >= 0)
                ans += c.areatriangle(p[i],p[j]);
            else ans -= c.areatriangle(p[i],p[j]);
        }
        return fabs(ans);
    }
};
int main(void)
{
    int n;
    double k;
    polygon pl;
    double x0,y0,r,x1,y1,x2,y2,D,E,F;
    int kase = 0;
    while(scanf("%d %lf",&n,&k) != EOF) {
        kase++;
        pl.input(n);
        scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
        D = 2.0 * (k * k * x1 - x2) / (1.0 - k * k);
        E = 2.0 * (k * k * y1 - y2) / (1.0 - k * k);
        F = (x2 * x2 + y2 * y2 - k * k * (x1 * x1 + y1 * y1) ) / (1.0 - k * k);
        r = sqrt(D * D + E * E - 4.0 * F) * 0.5;
        x0 = -D * 0.5;
        y0 = -E * 0.5;
        //cout << x0 << " " << y0 << " " << r << endl;
        printf("Case %d: %.11lf\n",kase,pl.areacircle(circle(x0,y0,r)));
    }
    return 0;
}

 

相关标签: 计算几何