牛客网暑期ACM多校训练营(第三场)J.Distance to Work 计算几何(多边形和圆的交面积)

链接:https://www.nowcoder.com/acm/contest/141/J
来源:牛客网
 

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

Eddy has graduated from college. Currently, he is finding his future job and a place to live. Since Eddy is currently living in Tien-long country, he wants to choose a place inside Tien-long country to live. Surprisingly, Tien-long country can be represented as a simple polygon on 2D-plane. More surprisingly, Eddy can choose any place inside Tien-long country to live. The most important thing Eddy concerns is the distance from his place to the working place. He wants to live neither too close nor too far to the working place. The more specific definition of "close" and "far" is related to working place.

Eddy has M choices to work in the future. For each working place, it can be represented as a point on 2D-plane. And, for each working place, Eddy has two magic parameters P and Q such that if Eddy is going to work in this place, he will choose a place to live which is closer to the working place than portion of all possible living place choices.

Now, Eddy is wondering that for each working place, how far will he lives to the working place. Since Eddy is now busy on deciding where to work on, you come to help him calculate the answers.

For example, if the coordinates of points of Tien-long country is (0,0), (2,0), (2, 2), (0, 2) in counter-clockwise order. And, one possible working place is at (1,1) and P=1, Q=2. Then, Eddy should choose a place to live which is closer to (1, 1) than half of the choices. The distance from the place Eddy will live to the working place will be about 0.7978845608.

输入描述:

The first line contains one positive integer N indicating the number of points of the polygon representing Tien-long country.
Each of following N lines contains two space-separated integer (xi, yi) indicating the coordinate of i-th points. These points is given in clockwise or counter-clockwise order and form the polygon.
Following line contains one positive integer M indicating the number of possible working place Eddy can choose from.
Each of following M lines contains four space-separated integer xj, yj, P, Q, where (xj, yj) indicating the j-th working place is at (xj, yj) and magic parameters is P and Q.

3 ≤ N ≤ 200
1 ≤ M ≤ 200
1 ≤ P < Q ≤ 200
|xi|, |yi|, |xj|, |yj| ≤ 103
It's guaranteed that the given points form a simple polygon.

输出描述:

Output M lines. For i-th line, output one number indicating the distance from the place Eddy will live to the i-th working place.

Absolutely or relatively error within 10-6 will be considered correct.

 

示例1

输入

4
0 0
2 0
2 2
0 2
1
1 1 1 2

输出

0.797884560809

示例2

输入

3
0 0
1 0
2 1
2
0 0 1 2
1 1 1 3

输出

1.040111537176
0.868735603376

 题目大意:

因为工作地点的原因,Eddy想在Tien-long country找一个地方作为家,但是Eddy不想理工作地点太远或者太近,因此他给出了一个P和Q,设以工作地点为中心的圆与Tien-long country交面积为S1,Tien-long country面积为S2,那么有(S2-S1)/S2=P/Q。

而Eddy想住在满足这样的P,Q的以工作地点为中心的圆的轨迹与Tien-long country的交线上。

现在给出Tien-long country的点表示多边形,和多个工作地点的坐标和P,Q,求Eddy能住在离工作地点多远的地方。

题目分析:

实际上就是求满足条件下圆的半径,这样我们只要二分答案套上多边形和圆的交面积模板就行了。

不过这里精度比较卡人,eps最好开到1e-12,并且都用long double;或者先用int存储到最后计算时才转成double。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l,m
#define rson m+1,r
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 5 * int(1e5) + 100;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = (int)1e9 + 7;
const long double eps = 1e-12;
inline int DB(long double x) {
	if (x<-eps) return -1;
	if (x>eps) return 1;
	return 0;
}
struct point {
	long double x, y;
	point() {}
	point(long double _x, long double _y) :x(_x), y(_y) {}
	point operator-(point a) {
		return point(x - a.x, y - a.y);
	}
	point operator+(point a) {
		return point(x + a.x, y + a.y);
	}
	long double operator*(point a) {
		return x*a.y - y*a.x;
	}
	point oppose() {
		return point(-x, -y);
	}
	long double length() {
		return sqrt(x*x + y*y);
	}
	point adjust(long double L) {
		L /= length();
		return point(x*L, y*L);
	}
	point vertical() {
		return point(-y, x);
	}
	long double operator^(point a) {
		return x*a.x + y*a.y;
	}
};
struct segment
{
	point a, b;
	segment() {}
	segment(point _a, point _b) :a(_a), b(_b) {}

	point intersect(segment s) {
		long double s1 = (s.a - a)*(s.b - a);
		long double s2 = (s.b - b)*(s.a - b);
		long double t = s1 + s2;
		s1 /= t;
		s2 /= t;
		return point(a.x*s2 + b.x*s1, a.y*s2 + b.y*s1);
	}

	point vertical(point p) {
		point t = (b - a).vertical();
		return intersect(segment(p, p + t));
	}
	int isonsegment(point p) {
		return DB(min(a.x, b.x) - p.x) <= 0 &&
			DB(max(a.x, b.x) - p.x) >= 0 &&
			DB(min(a.y, b.y) - p.y) <= 0 &&
			DB(max(a.y, b.y) - p.y) >= 0;
	}
};
struct circle {
	point p;
	long double R;
};
circle C;
point p[222];
int n;
long double cross_area(point a, point b, circle C) {
	point p = C.p;
	long double R = C.R;
	int sgn = DB((b - p)*(a - p));
	long double La = (a - p).length(), Lb = (b - p).length();
	int ra = DB(La - R), rb = DB(Lb - R);
	long double ang = acos(((b - p) ^ (a - p)) / (La*Lb));
	segment t(a, b);
	point s;
	point h, u, temp;
	long double ans, L, d, ang1;
	if (!DB(La) || !DB(Lb) || !sgn) ans = 0;
	else if (ra <= 0 && rb <= 0) ans = fabs((b - p)*(a - p)) / 2;
	else if (ra >= 0 && rb >= 0) {
		h = t.vertical(p);
		L = (h - p).length();
		if (!t.isonsegment(h) || DB(L - R) >= 0) ans = R*R*(ang / 2);
		else {
			ans = R*R*(ang / 2);
			ang1 = acos(L / R);
			ans -= R*R*ang1;
			ans += R*sin(ang1)*L;
		}
	}
	else {
		h = t.vertical(p);
		L = (h - p).length();
		s = b - a;
		d = sqrt(R*R - L*L);
		s = s.adjust(d);
		if (t.isonsegment(h + s)) u = h + s;
		else u = h + s.oppose();
		if (ra == 1) temp = a, a = b, b = temp;
		ans = fabs((a - p)*(u - p)) / 2;
		ang1 = acos(((u - p) ^ (b - p)) / ((u - p).length()*(b - p).length()));
		ans += R*R*(ang1 / 2);
	}
	return ans*sgn;
}
long double Xmult(point p1, point p2, point p0)
{
	return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
}
long double Polygon_area(int n, point *p)
{
	long double area = 0;
	for (int i = 1; i

 

你可能感兴趣的:(acm,计算几何)