UVA 11853 Paintball

https://vjudge.net/problem/UVA-11853

题目

一堆人玩水弹(也许是吧),知道他们的坐标和攻击范围,问你从西边到东边能否不被水弹砸。找出西边进入的位置和东边出去的位置。

$n\leqslant1000$

题解

最近一直在写水题……为了看看每道题使用的时间,还写了个计时器,但是这题用的时间太长了……

WA了一次,计算上罚时就是2小时了= =

坐标没看清楚,样例都纠结了半小时,然后少考虑了一种情况

按照紫书上的题解:

看有没有一条把这块地分成左右两边的路……

如果有就无解,没有就有解

然后从北边开始便利,找到与左右边界相交的最南边的坐标

AC代码

#include<bits/stdc++.h>
using namespace std;
#define REP(i,x,y) for(register int i=(x); i<(y); i++)
#define REPE(i,x,y) for(register int i=(x); i<=(y); i++)
#ifdef sahdsg
#define DBG(a,...) printf(a, ##__VA_ARGS__)
#else
#define DBG(a,...) (void)0
#endif

#define MAXN 1007
int n;
struct yuan {
	double r,x,y;
} arr[MAXN];

inline bool conn(int i, int j) {
	double rr = arr[i].r+arr[j].r;
	double dx = arr[i].x-arr[j].x;
	double dy = arr[i].y-arr[j].y;
	rr*=rr;
	dx*=dx;
	dy*=dy;
	return dx+dy<=rr;
}
bool vis[MAXN];

inline bool bfs1(int i) {
	queue<int> q;
	q.push(i);
	vis[i]=true;
	while(!q.empty()) {
		int now = q.front(); q.pop();
		if(arr[now].y-arr[now].r<=0) return true;
		REP(i,0,n) {
			if(!vis[i] && conn(now,i)) {
				q.push(i);
				vis[i]=true;
			}
		}
	}
	return false;
}

double ans1, ans2;
bool   has1, has2;

inline void bfs2(int i) {
	queue<int> q;
	q.push(i);
	while(!q.empty()) {
		int now = q.front(); q.pop();
		if(arr[now].x-arr[now].r<=0) {
			ans1=min(ans1,arr[now].y-sqrt(arr[now].r*arr[now].r-arr[now].x*arr[now].x));
		}
		if(arr[now].x+arr[now].r>=1000) {
			double dx=1000.0-arr[now].x;
			ans2=min(ans2,arr[now].y-sqrt(arr[now].r*arr[now].r-dx*dx));
		}
		REP(i,0,n) {
			if(!vis[i] && conn(now,i)) {
				q.push(i);
				vis[i]=true;
			}
		}
	}
}


int main() {
	#ifdef sahdsg
	freopen("in.txt","r",stdin);
	#endif
	
	while(~scanf("%d", &n)) {
		REP(i,0,n) {
			double &x=arr[i].x, &y=arr[i].y, &r=arr[i].r;
			scanf("%lf%lf%lf", &x, &y, &r);
		}
		bool f=true;
		memset(vis,0,sizeof vis);
		REP(i,0,n) {
			double &x=arr[i].x, &y=arr[i].y, &r=arr[i].r;
			if(!vis[i] && y+r>=1000) {
				if(bfs1(i)) {
					f=false;
					break;
				}
			}
		}
		if(!f) {
			puts("IMPOSSIBLE");
		} else {
			memset(vis,0,sizeof vis);
			ans1=ans2=1000;
			has1=has2=false;
			REP(i,0,n) {
				double &x=arr[i].x, &y=arr[i].y, &r=arr[i].r;
				if(!vis[i] && y+r>=1000) {
					bfs2(i);
				}
			}
			printf("0.00 %.2lf 1000.00 %.2lf\n", ans1, ans2);
		}
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/sahdsg/p/10422278.html
今日推荐