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

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值