Description:
鸡腿做了一个好梦呢!他化身钢铁侠大战全宇宙的各种怪物,并且取得了胜利。在梦的结尾,鸡腿开的飞船困在了一片废弃飞船群中,同时由于引擎故障,他只能在平面内移动。废弃飞船群可以描述为许多圆形的飞船,当然因为各种奇怪的原因,飞船可能叠加在一切。鸡腿也驾驶着飞船在这个平面中。一开始的时候鸡腿的飞船是不会和废弃的飞船有叠加部分的,鸡腿驶出这片区域时,可以蹭过某一个废弃飞船,但不能撞上更不能挤开它(质量问题),更不能和废弃飞船叠起来。鸡腿要立刻离开这片区域进行补给,你能告诉他现有条件下可以离开这片废弃飞船群吗?
N ≤ 300,数据组数 ≤ 5。
题解:
显然先把飞船的圆转移到障碍物的圆上,那么就变成了一个点是否能逃出生天。
如果两个圆相交,连边。
很容易想到的一种做法是判断点是否在一个环构成的多边形里。
*n元环没有多项式算法。
考虑换个思路,从这个点随机射一条射线,与它相交的边的权值为1。
现在要找一个权值和为奇数的环,这个显然就很简单了,BFS一就好了。
Code:
#include<cmath>
#include<cstdio>
#define db long double
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int N = 305;
const db eps = 1e-10;
const db theta = 0.5;
struct P {
db x, y;
P(db _x = 0, db _y = 0) {x = _x, y = _y;}
} a[N], b;
P angle(db x) {return P(cos(x), sin(x));}
P operator *(P a, P b) {return P(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}
P rotate(P a, db b) {return a * angle(b);}
db dis(P a, P b) {return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}
int n; db x, y, xx, yy, R, r[N];
int ans, bz[N][N], f[N][2], d[N * N * 2][2], d0;
int main() {
while(scanf("%d", &n) != EOF) {
fo(i, 1, n) scanf("%Lf %Lf %Lf", &a[i].x, &a[i].y, &r[i]);
scanf("%Lf %Lf %Lf", &x, &y, &R);
fo(i, 1, n) r[i] += R;
fo(i, 1, n) a[i] = rotate(a[i], theta);
b = rotate(P(x, y), theta); x = b.x; y = b.y;
b = rotate(P(3838, 4444), theta);
db k1 = (b.y - y) / (b.x - x), b1 = y - k1 * x;
fo(i, 1, n) fo(j, 1, n) bz[i][j] = 0;
fo(i, 1, n) fo(j, i + 1, n)
if(dis(a[i], a[j]) + eps < r[i] + r[j]) {
bz[i][j] = bz[j][i] = 1;
int k2 = (a[j].y - a[i].y) / (a[j].x - a[i].x), b2 = a[j].y - a[j].x * k2;
xx = (b2 - b1) / (k1 - k2); yy = xx * k1 + b1;
if(xx + eps > x && xx + eps > min(a[i].x, a[j].x) && xx - eps < max(a[i].x, a[j].x))
bz[i][j] = bz[j][i] = 2;
}
fo(i, 1, n) f[i][0] = f[i][1] = 0; ans = 1;
fo(i, 1, n) if(!f[i][0] && !f[i][1]) {
d[d0 = 1][0] = i; d[1][1] = 0;
fo(j, 1, d0) {
int u = d[j][0], v = d[j][1];
fo(j, 1, n) if(bz[u][j]) {
int nv = v ^ (bz[u][j] > 1);
if(!f[j][nv]) f[j][nv] = 1, d[++ d0][0] = j, d[d0][1] = nv;
}
}
if(f[i][1]) {
ans = 0; break;
}
}
if(ans) printf("YES\n"); else printf("NO\n");
}
}