Codeforces Gym 100625G Getting Through

G Getting Through

A long and straight corridor is fitted with a number of sensors. Each sensor has a certain range within which it can detect objects or persons. If a part of an object is within the sensor’s range, an alarm will go off. Otherwise, nothing will happen.

Ethan needs to traverse this corridor in order to do some spy stuff at the other end. The question is, can he pass through the corridor without being detected? Can he fit so easily that he can bring some equipment along, or does he have to wear some tight clothing? Or can he perhaps sent a robot through instead?

We model the corridor as being two-dimensional (we ignore the height), bounded by two straight lines. Each sensor is located inside the corridor or on a wall. Their scopes are well in between the two ends of the corridor. We model the person or robot going through as a circle. Given the layout, what is the maximum radius this circle can have so that it is possible to negotiate the corridor without being detected?


Input

On the first line one positive number: the number of test cases, at most 100. After that per test case:

· one line with a single integer w (1 ≤ w ≤ 100 000): the width of the corridor. The two walls are given by the lines x = 0 and x = w.

· one line with a single integer n (0 ≤ n ≤ 1 000): the number of sensors in the corridor.· n lines with three space-separated integers x, y and r (0 ≤ x ≤ w, -100 000 ≤ y ≤

100 000 and 1 ≤ r ≤ 100 000): the location and the range of each sensor, respectively.

The two ends of the corridor are at y = -∞ and y = +∞, or in less technical terms, they are far beyond the scope of all the sensors.


Output

Per test case:

· one line with one floating point number: the radius of the largest circular object (or per- son) that could pass through the corridor without being detected, assuming the object can (be) move(d) with absolute precision. If nothing could possibly get through, the output should be zero. The number should be accurate up to 10-6 absolute precision.

Sample in- and output


Input

3

10

2
2 0 3
7 12 4
10
2
2 0 3
7 8 4
10
2
2 0 3
7 4 4

Output


1.5
1.216991
0

题意:给定两堵墙和一些哨兵,每个哨兵有他们监视的区域(一个圆),给定这个圆的半径。要问从两堵墙之间通过的人的最大半径是多少,具体看图。

题解:先把任意两个点之间连一条边,边长为两圆心距离减去两圆半径。然后对于每个圆,连两条到两堵墙的边。把这些边按变长排序,从小到大扫一遍。扫过的点用并查集相连,并且用max更新答案。如果最后答案是负值那么说明无法穿过。注意,两堵墙之间要连一条边。

/* written by jiefangxuanyan */
#include <cstdio>
#include <algorithm>
#include <cmath>
const int N=1100;
struct item{
	int a,b;
	double l;
	item(){}
	item(int a,int b,double l):a(a),b(b),l(l){}
	bool operator<(const item &x)const{
		return l<x.l;
	}
}lns[N*N];
struct point{
	int x,y,r;
	double dis(const point &p)const{
		double dx=x-p.x,dy=y-p.y;
		return sqrt(dx*dx+dy*dy)-r-p.r;
	}
}in[N];
int fa[N];
int find(int a){
	if(fa[a]==a){
		return a;
	}
	int r=find(fa[a]);
	fa[a]=r;
	return r;
}
int main(){
	int cn;
	scanf("%d",&cn);
	for(int ci=0;ci<cn;ci++){
		int w,n;
		scanf("%d%d",&w,&n);
		for(int i=0;i<n;i++){
			scanf("%d%d%d",&in[i].x,&in[i].y,&in[i].r);
		}
		int cnt=0;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				lns[cnt++]=item(i,j,in[i].dis(in[j]));
			}
		}
		for(int i=0;i<n;i++){
			lns[cnt++]=item(i,n,in[i].x-in[i].r);
			lns[cnt++]=item(i,n+1,w-in[i].x-in[i].r);
		}
		lns[cnt++]=item(n,n+1,w);
		std::sort(lns,lns+cnt);
		double s=0;
		for(int i=0;i<=n+1;i++){
			fa[i]=i;
		}
		for(int i=0;i<cnt&&find(n)!=find(n+1);i++){
			int a=find(lns[i].a),b=find(lns[i].b);
			if(a!=b){
				fa[b]=a;
				s=std::max(lns[i].l,s);
			}
		}
		printf("%.10f\n",s/2);
	}
	return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值