light1358 - Fukushima Nuclear Blast【圆与多边形面积的交+二分】

1358 - Fukushima Nuclear Blast
Time Limit: 5 second(s)Memory Limit: 32 MB

One of the most disastrous nuclear accidents in history has taken place at Japan's Fukushima Daiichi nuclear plant. Reactor buildings have been rocked by explosions, caused after damage was sustained from a massive earthquake and tsunami on 11th march and thus releasing dangerous radiation of unspecified proportions into the air.

The radiation is spreading and it's not a threat only to Japan but also to other countries. If the level of radiation reaches a high level, it will surely cause harms to human health as well as the environment.

You, one of the great programmers in the city, have planned to find the zones that are vulnerable to radiation. If you can measure the level of radiation in a certain city, further actions can be taken to prevent the people from radiation related health consequences. So, at first you want to find the time in which a certain percentage of an area is under radiation threat.

So, at first you modeled the map of a city in 2D space as a simple polygon [1]. You denoted the origin of the explosion as a single point. From this origin, the radiation spreads circularly. You plotted the map such that in each unit of time the radius of the radiation grows one unit. Now, you want to find the time when P% of the area of a city is under threat of radiation.

Input

Input starts with an integer T (≤ 70), denoting the number of test cases.

Each test case starts with a blank line. The next line contains an integer n (3 ≤ n ≤ 5000) denoting the number of vertices of the polygon. Each of the next n lines will contain two integers xi, yi denoting the co-ordinate of a vertex of the polygon. The vertices will be given in anticlockwise order. The next line contains 3 integers rx, ry and P (0 < P ≤ 100), where (rx, ry) denotes the co-ordinate of the origin of explosion and P denotes the percentage. All values for the co-ordinates are between -200 to 200 (inclusive).

Output

For each case, print the case number and the time when exactly P% of the total area is under threat of radiation. Round the time to nearest integer.

Sample Input

Output for Sample Input

2

 

3

-5 0

5 0

0 5

0 0 100

 

4

0 0

5 0

3 1

5 6

0 0 17

Case 1: 5

Case 2: 2

Notes

1.      In geometry, a simple polygon is a closed polygonal chain of line segments in the plane which do not have points in common other than the common vertices of pairs of consecutive segments.

2.      The judge data is prepared such that the result (before rounding) will not be between x.3 to x.7. For example, the result can be like 5.8, 24.3 or 81.791. But the result will not be like 24.5, 78.4, etc.


题意已知圆与多边形相交的面积:求半径r

刚看这题是明显是二分+圆与多边形面积交于是写了一下测试数据通过然后提交死活都不过无奈之下找了一份外国人的ac代码看了也没有什么特别坑的地方可能是我的圆与多边形相交面积模板不够强吧:

附:网上找到的外国的ac代码

#include <iostream>
#include <vector>
#include <cmath>
#include <cstdio>
using namespace std;

const double PI  = acos(-1.0);
const double TAU = 2 * PI;
const double EPS = 1e-8;

int sig(double x) {return x < -EPS ? -1 : x > EPS ? 1 : 0;}
template<class T> T pow2(T x) {return x*x;}

struct Vector {
    double x, y;
    Vector() {}
    Vector(double x, double y): x(x), y(y) {}
    Vector operator -(const Vector &v) const {return Vector(x-v.x, y-v.y);}
    Vector operator +(const Vector &v) const {return Vector(x+v.x, y+v.y);}
    Vector operator *(double s) const {return Vector(x*s, y*s);}
    Vector operator /(double s) const {return Vector(x/s, y/s);}
    
    double operator *(const Vector &v) const {return x*v.x + y*v.y;}
    double operator ^(const Vector &v) const {return x*v.y - y*v.x;}
    
    double len2() {return x*x + y*y;}
    double len() {return sqrt(len2());}
    double ang() {return atan2(y, x);}
    Vector e() {return *this / len();}
};

typedef Vector Point;
typedef vector<Point> Polygon;


struct Segment {
    Point a, b;
    Segment() {}
    Segment(Point a, Point b): a(a), b(b) {}
};

typedef Segment Line;

struct Circle {Point o; double r;};


// dot & cross product
double   dot(Point o, Point a, Point b) {return (a-o)*(b-o);}
double cross(Point o, Point a, Point b) {return (a-o)^(b-o);}


// Nearest point in line
Point project(Point p, Line l) {
    Vector vl = l.b - l.a;
    return l.a + vl * ((p - l.a) * vl) / vl.len2();
}


// distance from point to line
double dis_p_li(Point p, Line l) {
    // dis(high) = area / bottom
    return fabs(cross(l.a, l.b, p)) / (l.a - l.b).len();
}
// distance from point to segment
double dis_p_seg(Point p, Segment s) {
    if (dot(s.a, s.b, p) > 0
        && dot(s.b, s.a, p) > 0) return dis_p_li(p, Line(s));
    else
        return min((p - s.a).len(), (p - s.b).len());
}


// The segment which line intersect with circle
// Ensure intersect(Circle c, Line l) is `true'
Segment cross_cir_li(Circle c, Line l) {
    Point p = project(c.o, l);
    Vector v = l.a - l.b;
    v = v.e() * sqrt(pow2(c.r) - (c.o - p).len2());
    return  Segment(p + v, p - v);
}


// signed area of intersection of circle(c.o, c.r) and
//  triangle(c.o, s.a, s.b) [cross(a-o, b-o)/2]
double fix_acute(double th) {return th<-PI ? th+TAU : th>PI ? th-TAU : th;}
double area_cir_tri(Circle c, Segment s)
{
    double disoa = (c.o - s.a).len(), disob = (c.o - s.b).len();
    
    // sector
    if (sig(dis_p_seg(c.o, s) - c.r) >= 0)
        return fix_acute((s.b - c.o).ang() - (s.a - c.o).ang())
            * pow2(c.r) / 2.0;

    // triangle
    if (sig(disoa - c.r) <= 0 && sig(disob - c.r) <= 0)
        return cross(c.o, s.a, s.b) / 2.0;

    // three part: (A, a) (a, b) (b, B)
    Segment rs = cross_cir_li(c, Line(s));
    return area_cir_tri(c, Segment(s.a, rs.a))
        + area_cir_tri(c, Segment(rs.a, rs.b))
        + area_cir_tri(c, Segment(rs.b, s.b));
}
// area of intersecion of circle(c.o, c.r) and simple polyson(p[])
//  (ccw or cw is ok)
double area_cir_polygon(Circle c, Polygon p)
{
    double res = .0;
    int n = p.size();
    for (int i = 0; i < n; ++ i)
        res += area_cir_tri(c, Segment(p[i], p[(i+1)%n]));
    return fabs(res);
}


// area of polygon (ccw or cw is ok)
double polygon_area(Polygon P) {
    double r = .0;
    int n = P.size();
    for (int i = 0; i < n; ++ i)
        r += (P[i] ^ P[(i+1)%n]);
    return fabs(r) / 2;
}

int main(int argc, char *argv[])
{
    int t;
    cin >> t;
    for (int cas = 1; cas <= t; cas++) {
        int n;
        cin >> n;
        Polygon p(n);
        for (int i = 0; i < n; i++)
            cin >> p[i].x >> p[i].y;
        Circle c;
        cin >> c.o.x >> c.o.y;
        double s;
        cin >> s;
        s = polygon_area(p) * s / 100;

        double l = 0, r = 3000;
        while (l + EPS < r) {
            c.r = (l + r) / 2;
            if (sig(area_cir_polygon(c, p) - s) >= 0)
                r = c.r;
            else
                l = c.r;
        }
        printf("Case %d: %.0lf\n", cas, l);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值