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.
刚看这题是明显是二分+圆与多边形面积交于是写了一下测试数据通过然后提交死活都不过无奈之下找了一份外国人的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;
}