uva 11177 Fighting Against a Polygonal Monster(凸包与圆的面积交)

来源:互联网 发布:skypixel软件 编辑:程序博客网 时间:2024/05/16 00:48
Problem C
Fighting against a Polygonal Monster
Input: Standard Input
Output: Standard Output

You're fighting against a monster. You have a special weapon that can shoot a laser beam. The laser beam can be seen as a cylinder along the z-axis, So when look from above the XY plane, the laser beam is actually a circle centered at (0,0) (yes, you cannot change the position of center). The monster is a convex polygon (well, you may think of it as a very thin prism) with n vertices surrounding the origin (i.e. (0,0) is strictly inside the monster, not on his boundary).

You know that, when the common area of the laser beam and the monster is at least R, the monster dies. Since larger laser beam consumes more power, you're interested in the minimum radius of the laser beam.

Write a program to find the minimum radius. It is guaranteed that (0 £ R £ A), where A is the area of the monster.

Input
The input consists at most 10 cases. Each case starts with a single integer n (3 £ n £ 50) and a floating-point number R followed by n lines of two real numbers: the coordinates of the monster. The points are arranged in counter-clockwise order or clockwise order. The last test case is followed by a single zero, which should not be processed. The meaning of N and R are given in the problem statement.

Output
For each test case, print the case number and the minimum radius, to 2 decimal places. Inputs will be such that small precision errors will not change the visible output if you use double-precision floating-point numbers.

Sample Input
3 1.60
-1 -1
1 -1
0 1
0


 Output for Sample Input

Case 1: 0.93


Problem setter: Rujia Liu
Alternative Solutions: Wenbin Tang, Yiming Li

Originally used in the Sichuan Team Selection Contest for NOI, 2006.


题意:有个凸N边形,一定包含原点。 然后有一个以原点为圆心的圆,要使圆与凸边形的面积交等于S,问圆的半径应该为多大。


思路:先将凸包极角排序,二分圆的半径。然后将凸多边形对于原点进行三角剖分。

对于每个三角形OAB和圆的位置关系有4种情况,

1.A,B在圆内,则计算三角形的面积。

2.A,B有一个在圆内,则计算一个三角形和一个扇形的面积。

3.A,B在圆外,如果线段AB与圆有交点,则计算两个扇形和一个三角形的面积。否则只需计算一个扇形的面积。


代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <ctime>#include <bitset>#include <algorithm>#include <set>#include <string>#include <vector>#include <list>#include <stack>#include <queue>#include <deque>using namespace std;#define LL long longconst double eps = 1e-10;const double pi = acos(-1.0);int cmp(double x) {    if(fabs(x) < eps) return 0;    if(x > 0)return 1;    return -1;}inline double sqr(double x) {    return x * x;}struct point {    double x, y;    point(){}    point(double a, double b): x(a), y(b) {}    void input(){        scanf("%lf%lf",&x,&y);    }    friend point operator + (const point &a, const point &b) {        return point(a.x + b.x, a.y + b.y);    }    friend point operator - (const point &a, const point &b) {        return point(a.x - b.x, a.y - b.y);    }    friend bool operator == (const point &a, const point &b) {        return cmp(a.x - b.x) == 0 && cmp(a.y - b.y) == 0;    }    friend bool operator < (const point &a, const point& b) {        return cmp(a.x - b.x) < 0 || cmp(a.x - b.x) == 0 && cmp (a.y - b.y) < 0;    }    friend point operator * (const point &a, const double &b) {        return point(a.x * b, a.y * b);    }    friend point operator * (const double &a, const point &b) {        return point(a * b.x, a * b.y);    }    friend point operator / (const point &a, const double &b) {        return point(a.x / b, a.y / b);    }    double norm(){        return sqrt(sqr(x) + sqr(y));    }};double det(const point &a, const point &b) {    return a.x * b.y - a.y * b.x;}double dot(const point &a, const point &b) {    return a.x * b.x + a.y * b.y;}double dist(const point &a, const point &b) {    return (a - b).norm();}double Angle(point a, point b) {    if(cmp(dot(a, b) - a.norm() * b.norm()) == 0) return 0;    if(cmp(dot(a, b) + a.norm() * b.norm()) == 0) return pi;    return acos(dot(a,b) / a.norm() / b.norm()); }double angle(point p) {    return atan2(p.y, p.x);}point rotate_point(const point &p, double A){    double tx = p.x, ty = p.y;    return point(tx * cos(A) - ty * sin(A), tx * sin(A) + ty * cos(A));}point rotate_point(const point &p, double sint, double cost) {    double tx = p.x, ty = p.y;    return point(tx * cost - ty * sint, tx * sint + ty * cost);}struct line {    point a, b;    line(){}    line(point x, point y):a(x),b(y){}    void input() {        a.input();        b.input();    }};void point_pro_line(const point p, const point s, const point t, point &cp) {      double r = dot(t - s, p - s) / dot (t - s, t - s);    cp = s + r * (t - s);}bool point_pro_segment(const point p, const point s, const point t, point &cp) {    if(cmp(dot(p - s, t - s))<0) {        cp = s;        return 0;    }    if(cmp(dot(p - t, s - t))<0) {        cp = t;        return 0;    }    double r = dot(t - s, p - s) / dot (t - s, t - s);    cp = s + r * (t - s);    return 1;}bool point_on_segment(point p, point s, point t) {    return cmp(det(p - s, t - s))== 0 && cmp(dot(p - s, p - t)) <= 0;}bool parallel(line a, line b) {    return !cmp(det(a.a - a.b, b.a - b.b));}bool line_cross_line(line a, line b, point &res){    if(parallel(a, b)) return false;    double s1 = det(a.a - b.a, b.b - b.a);    double s2 = det(a.b - b.a, b.b - b.a);    res = (s1 * a.b - s2 * a.a) / (s1 - s2);    return true;}int segment_cross_segment(const point& a1,const point& a2,const point& b1,const point& b2, point& res) {    double c1 = det(a2 - a1, b1 - a1);    double c2 = det(a2 - a1, b2 - a1);    double c3 = det(b2 - b1, a1 - b1);    double c4 = det(b2 - b1, a2 - b1);    if (cmp(c1) * cmp(c2) < 0 && cmp(c3) * cmp(c4) < 0) {        res.x = (b1.x * c2 - b2.x * c1) / (c2 - c1);        res.y = (b1.y * c2 - b2.y * c1) / (c2 - c1);        return 1;    }    if(point_on_segment(a1, b1, b2)) {        res = a1;        return 2;    }    if(point_on_segment(a2, b1, b2)) {        res = a2;        return 2;    }    if(point_on_segment(b1, a1, a2)) {        res = b1;        return 2;    }    if(point_on_segment(b2, a1, a2)) {        res = b2;        return 2;    }    return 0;}int segment_cross_segment(const line& l1, const line& l2, point& res) {    point a1 = l1.a, a2 = l1.b, b1 = l2.a, b2 = l2.b;    double c1 = det(a2 - a1, b1 - a1);    double c2 = det(a2 - a1, b2 - a1);    double c3 = det(b2 - b1, a1 - b1);    double c4 = det(b2 - b1, a2 - b1);    if (cmp(c1) * cmp(c2) < 0 && cmp(c3) * cmp(c4) < 0) {        res.x = (b1.x * c2 - b2.x * c1) / (c2 - c1);        res.y = (b1.y * c2 - b2.y * c1) / (c2 - c1);        return 1;    }    if(point_on_segment(a1, b1, b2)) {        res = a1;        return 2;    }    if(point_on_segment(a2, b1, b2)) {        res = a2;        return 2;    }    if(point_on_segment(b1, a1, a2)) {        res = b1;        return 2;    }    if(point_on_segment(b2, a1, a2)) {        res = b2;        return 2;    }    return 0;}struct circle {    point c;    double r;    circle() {}    circle(point _c, double _r): c(_c), r(_r) {}    void input() {        c.input();        scanf("%lf", &r);    }    double perimeter() {        return 2 * pi * r;    }    double area() {        return sqr(r) * pi;    }};bool point_on_circle(const point& p, const circle& c) {    return cmp((p - c.c).norm() - c.r) == 0;}bool point_in_circle(const point& p, const circle& c) {    return cmp((p - c.c).norm() - c.r) < 0;}int circle_cross_line(circle C, line l, double &t1, double &t2, point res[]) {    double a = l.b.x - l.a.x;    double b = l.a.x - C.c.x;    double c = l.b.y - l.a.y;    double d = l.a.y - C.c.y;    double e = sqr(a) + sqr(c);    double f = 2 * (a * b + c * d);    double g = sqr(b) + sqr(d) - sqr(C.r);    double delta = f * f - 4 * e * g;    if(cmp(delta) < 0) return 0;    if(cmp(delta) == 0) {        t1 = t2 = -f / (2 * e);        res[0] = point(l.a.x + t1 * a, l.a.y + t1 * c);        return 1;    }    t1 = (-f - sqrt(delta)) / (2 * e);    t2 = (-f + sqrt(delta)) / (2 * e);    res[0] = point(l.a.x + t1 * a, l.a.y + t1 * c);    res[1] = point(l.a.x + t2 * a, l.a.y + t2 * c);    return 2;}int circle_cross_circle(circle C1, circle C2, point res[]) {    double d = (C1.c - C2.c).norm();    if(cmp(C1.r + C2.r - d) < 0 || cmp(fabs(C1.r - C2.r) - d) > 0) return 0;    if(cmp(C1.r + C2.r - d) == 0 || cmp(fabs(C1.r - C2.r) - d) == 0) {        if(cmp(C2.r - C1.r) > 0) swap(C1, C2);        res[0] = (C2.c - C1.c) / d * C1.r + C1.c;        return 1;    }    double cost = (sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2 * C1.r * d);    double sint = sqrt(1.0 - sqr(cost));    point p = (C2.c - C1.c) / d * C1.r;    res[0] = C1.c + rotate_point(p, -sint, cost);    res[1] = C1.c + rotate_point(p, sint, cost);    return 2;}struct polygon_convex {    vector<point> P;    polygon_convex(int size = 0) {        P.resize(size);    }    point& operator [](int index) {        return P[index];    }    int size() {        return P.size();    }};bool comp_less(const point& a, const point& b) {    return cmp(a.x - b.x) < 0 || cmp(a.x - b.x) == 0 && cmp(a.y - b.y) < 0;}polygon_convex convex_hull(vector<point>& a) {    polygon_convex res(2 * a.size() + 5);    sort(a.begin(), a.end(), comp_less);    a.erase(unique(a.begin(), a.end()), a.end());    int m = 0;    for(int i = 0; i < a.size(); i++) {        while(m > 1 && cmp(det(res[m - 1] - res[m - 2], a[i] - res[m - 2])) <= 0) m--;        res[m++] = a[i];    }    int k = m;    for(int i = int(a.size()) - 2; i >= 0; i--) {        while(m > k && cmp(det(res[m - 1] - res[m - 2], a[i] - res[m - 2])) <= 0) m--;        res[m++] = a[i];    }    res.P.resize(m);    if(a.size() > 1) res.P.resize(m - 1);    return res;}vector<point> Pin;polygon_convex pc;double S;int n;double sector_area(const point& a, const point& b, double r) {    double A = angle(a) - angle(b);    while(A <= 0) A += pi + pi;    while(A >= pi + pi) A -= pi + pi;    A = min(A, pi + pi - A);    return sqr(r) * A / 2;}double Area(point& a, point& b, double& r) {    int da = cmp(r - a.norm()) > 0;    int db = cmp(r - b.norm()) > 0;    double t1, t2;    int num;    circle cir(point(0.0, 0.0), r);    point p[2];    if(da && db) {        return fabs(det(a, b)) * 0.5;    }    if(da && !db) {        circle_cross_line(cir, line(a, b), t1, t2, p);            if(cmp(t1) >= 0 && (t1 - 1) <= 0) {                return sector_area(b, p[0], r) + fabs(det(a, p[0]) * 0.5);            }            return sector_area(b, p[1], r) + fabs(det(a, p[1]) * 0.5);                   }    if(!da && db) {        circle_cross_line(cir, line(a, b), t1, t2, p);            if(cmp(t1) >= 0 && cmp(t1 - 1) <= 0) {                return sector_area(a, p[0], r) + fabs(det(b, p[0]) * 0.5);            }            return sector_area(a, p[1], r) + fabs(det(b, p[1]) * 0.5);    }    if(!da && !db) {        if(circle_cross_line(cir, line(a, b), t1, t2, p) == 2) {            if(cmp(t1) >= 0 && cmp(t1 - 1) <= 0 && cmp(t2) >= 0 && cmp(t2 - 1) <= 0) {                return sector_area(a, p[0], r) + sector_area(p[1], b, r) + fabs(det(p[0], p[1])) * 0.5;            }        }        return sector_area(a, b, r);    }    return 0;}double calc(double r) {    double ret = 0;    int n = pc.size();    #define next(i) ((i + 1) % n)    for(int i = 0; i < n; i++) {        ret += Area(pc[i], pc[next(i)], r);    }    return ret;}int main() {    int cas = 0;    while(scanf("%d", &n) && n) {        scanf("%lf", &S);        Pin.resize(n);        for(int i = 0; i < n; i++) Pin[i].input();        pc = convex_hull(Pin);        double l, r, mid, ans;        l = 0;        r = 100000.0;        while(r - l >= 1e-4) {            mid = (l + r) * 0.5;            ans = calc(mid);            if(ans < S) l = mid;            else r = mid;        }        printf("Case %d: %.2f\n", ++cas, mid);    }    return 0;}


1 0
原创粉丝点击