Snakes(并查集)



Snakes
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
POJ 2588

Description

Buffalo Bill wishes to cross a 1000x1000 square field. A number of snakes are on the field at various positions, and each snake can strike a particular distance in any direction. Can Bill make the trip without being bitten?

Input

Assume that the southwest corner of the field is at (0,0) and the northwest corner at (0,1000). The input consists of a line containing n <= 1000, the number of snakes. A line follows for each snake, containing three real numbers: the (x,y) location of the snake and its strike distance. The snake will bite anything that passes closer than this distance from its location.

Output

Bill must enter the field somewhere between the southwest and northwest corner and must leave somewhere between the southeast and northeast corners. 

If Bill can complete the trip, give coordinates at which he may enter and leave the field. If Bill may enter and leave at several places, give the most northerly. If there is no such pair of positions, print "Bill will be bitten." 

Sample Input

3
500 500 499
0 0 999
1000 1000 200

Sample Output

Bill enters at (0.00, 1000.00) and leaves at (1000.00, 800.00).

译:
[Description]
Bill 想要穿过一片 1000*1000 的荒漠,但是荒漠中有一些蛇,每条蛇都有一个攻击距离,
Bill 能否不被蛇攻击到完成旅行吗?
[Input]
假设地图的西南角为(0,0),西北角为(0,1000)。
输入第一行一个数 N,表示蛇的数量,接下来 N 行,第 i+1 行三个实数,xi,yi,di 分别第 i 条
蛇的位置和攻击距离,当人处于攻击范围之内时,会被蛇攻击。
[Output]
Bill 必须从西边进入荒漠,而从东边离开,可以朝任意方向四个方向走,如果能够完成,按
样例格式输出 Bill 进入和离开荒漠的位置,如果有多个位置,输出最北边的位置,如果不
能完成,输出"Bill will be bitten."
[Sample Input]
3
500 500 499
0 0 999
1000 1000 200
[Sample Output]
Bill enters at (0.00, 1000.00) and leaves at (1000.00, 800.00).
[Hint]
N<=1,000

Snakes(并查集)_第1张图片

一道经典的并查集的题

#include
#include
#include
#include
#include
using namespace std;
const int MAXN=1010;
struct snake
{
	double x,y,r;
}s[MAXN];

struct node 
{
	double up,down;
	int index;
}l[MAXN],r[MAXN];

int n;
bool map[MAXN][MAXN];
int fa[MAXN];
int lcnt=0,rcnt=0;
double lans=-1,rans=-1;
double lup=1000,ldown=0,rup=1000,rdown=0;
//lup表示左边界可用区间的最高点,ldown左边界可用区间的最低点

int find(int x)
{
	if(x==fa[x])	return fa[x];
	return fa[x]=find(fa[x]);
}

bool check(node t[],double x,int n)
{
	for(int i=0;ix && t[i].down>n;
	memset(map,0,sizeof(map));
	for(int i=0;i1000)	map[0][i]=map[i][0]=true;
		
		if(s[i].y-s[i].r<0)		map[n+1][i]=map[i][n+1]=true;
				
		//与左边界的关系
		if(s[i].x-s[i].r<0)
		{
			l[lcnt].up=s[i].y+sqrt(s[i].r*s[i].r-s[i].x*s[i].x);
			l[lcnt].down=s[i].y-sqrt(s[i].r*s[i].r-s[i].x*s[i].x);
			l[lcnt++].index=i;
		}
		
		//与右边界的关系
		if(s[i].x+s[i].r>1000)
		{
			r[rcnt].up=s[i].y+sqrt(s[i].r*s[i].r-(1000-s[i].x)*(1000-s[i].x));
			r[rcnt].down=s[i].y-sqrt(s[i].r*s[i].r-(1000-s[i].x)*(1000-s[i].x));
			r[rcnt++].index=i;
		}
	}
	
	return;
}
void work()
{
	for(int i=1;i sqrt((s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y)))
				map[i][j]=map[j][i]=true;
		}
		
	for(int i=0;i<=n;i++)
		for(int j=i+1;j<=n+1;j++)
		{
			if(map[i][j])
			{
				int x=find(i);
				int y=find(j);
				if(x!=y)	fa[y]=x;
			}
		}
	return;
}

void solve_l()
{
	//找出可用区间(ldown,lup),因为如果find(a)==find(0)
	
	//圆a又与左边界相交,相交部分到最高点1000,都是不可用的
	
	for(int i=0;ildown)
			ldown=l[i].up;
	}
	
	//判断最高点1000是否可用,如果在圆和左边界相交区域则不可用
	
	if(check(l,1000,lcnt) && lup==1000)	lans=1000;
	
	//最高点一定坐落在左边界的最高点或与圆的交点
	
	//所以判断交点是否在可用区间,判断交点是否可用,判断lans是否值得替换
	
	for(int i=0;i=ldown && check(l,l[i].up,lcnt) && lans=ldown && check(l,l[i].down,lcnt) && lansrdown)
			rdown=l[i].up;
	}
	
	//判断最高点1000是否可用,如果在圆和右边界相交区域则不可用
	
	if(check(r,1000,rcnt) && rup==1000)	rans=1000;
	
	//最高点一定坐落在右边界的最高点或与圆的交点
	
	//所以判断交点是否在可用区间,判断交点是否可用,判断rans是否值得替换
	for(int i=0;i=rdown && check(r,r[i].up,rcnt) && rans=rdown && check(r,r[i].down,rcnt) && rans


你可能感兴趣的:(并查集,停课集训)