题目链接:http://poj.org/problem?id=2588

Snakes

Time Limit: 1000MS   Memory Limit: 65536K
 

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).

Source

 
 
题目大意:有一个1000*1000的地图,地图上有一些蛇现在给出蛇的坐标和攻击半径(攻击范围是一个圆),Bill不能从蛇的攻击范围穿过,Bill 必须从西边进入荒漠,
     而从东边离开,可以朝任意方向四个方向走,如果能够完成,按样例格式输出 Bill 进入和离开荒漠的位置,如果有多个位置,输出最北边的位置,
     如果不能完成,输出"Bill will be bitten."
 
解题思路:这道题吧n条蛇的攻击范围,当成并查集的对象来进行,特别的吧图的最高点(n+1),最低点(0)也加入并查集,如果f[n+1]==f[0],这肯定不能到达,
     否则的话,通过判断左右边界与蛇攻击区域的相交关系,判断边界是否可行,可行的话,在此过程中找出最北方的点,具体见代码注释分析~~~
 
代码如下:
 #include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
#define maxn 1005 /*-------------上下左右边界判断-------------*/
struct UpDown{
double x, y, area;
}snack[maxn];
struct LeftRight{
double up, down;
int i;
}le[maxn], ri[maxn]; int father[maxn], map[maxn][maxn]; //----------检查当前出入最高点是否可用--------------------
bool check(LeftRight *p, double x, int n){
for (int i = ; i < n; i++){
if (p[i].up>x&&p[i].down < x)
return false;
}
return true;
} //-------------并查集判断构造的点(包括上下边界)是否连通-------------------
int getf(int x){
return father[x] != x ? father[x] = getf(father[x]) : x;
} int main()
{
int n, i, j;
while (cin >> n){
for (i = ; i <= n + ; i++)
father[i] = i;
int L = , R = ;
memset(map, , sizeof(map));
for (i = ; i <= n; i++){
cin >> snack[i].x >> snack[i].y >> snack[i].area; //-----------建立上下关系---------------
if (snack[i].y + snack[i].area > )
map[][i] = map[i][] = ;
if (snack[i].y - snack[i].area < )
map[n + ][i] = map[i][n + ] = ; //---------建立左右关系------------------
if (snack[i].x - snack[i].area < ){
le[L].up = snack[i].y + sqrt(pow(snack[i].area, ) - pow(snack[i].x, ));
le[L].down = snack[i].y - sqrt(pow(snack[i].area, ) - pow(snack[i].x, ));
le[L++].i = i;
}
if (snack[i].x + snack[i].area >){
ri[R].up = snack[i].y + sqrt(pow(snack[i].area, ) - pow(( - snack[i].x), ));
ri[R].down = snack[i].y - sqrt(pow(snack[i].area, ) - pow(( - snack[i].x), ));
ri[R++].i = i;
}
} //-------------通过圆心判断各区域相交情况-------------------
for (i = ; i < n; i++)
for (j = i + ; j <= n; j++){
if (snack[i].area + snack[j].area>sqrt(pow((snack[i].x - snack[j].x), ) + pow((snack[i].y - snack[j].y), )))
map[i][j] = map[j][i] = ;
} //-----------并查集处理------------------
for (i = ; i <= n; i++)
for (j = i + ; j <= n + ; j++){
if (map[i][j]){
int x = getf(i), y = getf(j);
if (x != y)
father[y] = x;
}
} if (getf(n + ) == getf())
cout << "Bill will be bitten." << endl; else{
double Lflag = -, Rflag = -, Lup = , Ldown = , Rup = , Rdown = ; //-----------找到最高可用左边界------------------------
for (i = ; i < L; i++){
if (getf(le[i].i) == getf() && le[i].down < Lup)
Lup = le[i].down;
if (getf(le[i].i) == getf(n + ) && le[i].up >Ldown)
Ldown = le[i].up;
} if (check(le, , L) && Lup == )
Lflag = ; for (i = ; i < L; i++){
if (le[i].up <= Lup&&le[i].up >= Ldown&&check(le, le[i].up, L) && Lflag < le[i].up)
Lflag = le[i].up;
if (le[i].down <= Lup&&le[i].down >= Ldown&&check(le, le[i].down, L) && Lflag < le[i].down)
Lflag = le[i].down;
}
//---------------------------------------------------------------------- //--------------------------===右边界处理-----------------------
for (i = ; i < R; i++){
if (getf(ri[i].i) == getf() && ri[i].down < Rup)
Rup = ri[i].down;
if (getf(ri[i].i) == getf(n + ) && ri[i].up >Rdown)
Rdown = ri[i].up;
}
if (check(ri, , R) && Rup == )
Rflag = ;
for (i = ; i < R; i++){
if (ri[i].up <= Rup&&ri[i].up >= Rdown&&check(ri, ri[i].up, R) && Rflag < ri[i].up)
Rflag = ri[i].up;
if (ri[i].down <= Rup&&ri[i].down >= Rdown&&check(ri, ri[i].down, R) && Rflag < ri[i].down)
Rflag = ri[i].down;
}
if (L == )
Lflag = ;
if (R == )
Rflag = ;
if (Rflag < || Lflag < )
cout << "Bill will be bitten." << endl;
else
printf("Bill enters at (0.00, %.2lf) and leaves at (1000.00, %.2lf).\n", Lflag, Rflag);
}
}
return ;
}
 

[POJ 2588]--Snakes(并查集)的更多相关文章

  1. poj 2524 (并查集)

    http://poj.org/problem?id=2524 题意:在一所学校里面的人,都有宗教信仰,不过他们的宗教信仰有可能相同有可能不同,但你又不能直接去问他们,但你可以问他们和谁是同一个宗教.通 ...

  2. [POJ 2588] Snakes

    同swustoj 8 Snakes Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1015   Accepted: 341 ...

  3. poj 1456 Supermarket - 并查集 - 贪心

    题目传送门 传送点I 传送点II 题目大意 有$n$个商品可以销售.每个商品销售会获得一个利润,但也有一个时间限制.每个商品需要1天的时间销售,一天也只能销售一件商品.问最大获利. 考虑将出售每个物品 ...

  4. poj 2492(关系并查集) 同性恋

    题目;http://poj.org/problem?id=2492 卧槽很前卫的题意啊,感觉节操都碎了, t组测试数据,然后n,m,n条虫子,然后m行,每行两个数代表a和b有性行为(默认既然能这样就代 ...

  5. poj 1182 (关系并查集) 食物链

    题目传送门:http://poj.org/problem?id=1182 这是一道关系型并查集的题,对于每个动物来说,只有三种情况:同类,吃与被吃: 所以可以用0,1,2三个数字代表三种情况,在使用并 ...

  6. Poj(1182),种类并查集

    题目链接:http://poj.org/problem?id=1182 再次熟练种类并查集,又积累点经验,和技巧,rank 0 2 1 先计算father[x] ,再更新rank[x]; #inclu ...

  7. Poj(1703),种类并查集

    题目链接:http://poj.org/problem?id=1703 已经不是第一次接触种类并查集了,直到今天才搞懂. 感谢红黑联盟,感谢杰哥!!! 每个节点只要关系确定,不管是不是同一个集合里面, ...

  8. POJ 1182 食物链 [并查集 带权并查集 开拓思路]

    传送门 P - 食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit  ...

  9. poj 2513 欧拉回路+并查集推断是否联通+Trie树

    http://poj.org/problem? id=2513 最初看到 第一感觉---map  一看250000的数据量 果断放弃 然后记得曾经看过.trie取代map.尤其当数据量特别大的时候 学 ...

随机推荐

  1. PrintWriter与outputStream区别

    网上截取: printWriter:我们一般用来传的是对像 而outputStream用来传的是二进制,故上传文件时,一定要使用此. PrintWriter以字符为单位,支持汉字,OutputStre ...

  2. mysql server5.6.28 修改数据目录

    1.查看配置文件 mysql --help | grep my.cnf 列出使用哪个配置文件(顺序推) 2.service mysql stop 3.创建新目录 mkdir /data 4.迁移之前的 ...

  3. iOS自动自动隐藏软键盘

    自动隐藏软键盘,分为两步,一个是单击软键盘外部任意空间:另外一个是单击软键盘上的return键.下面依次实现 单击软键盘外部空间键隐藏软键盘: 一:在viewDidLoad中添加一个UITabGest ...

  4. js 中的bind函数

    bind是Function.prototype中内置函数 作用是指定函数作用域 代码参考 http://blog.csdn.net/load_life/article/details/7200381 ...

  5. 帝国cms7.2自定义列表建立tag效果 代码 教程

    统计记录:(如:select count(*) as total from phome_ecms_news where classid=1 and checked=1) 注:这句SQL的意思是查找统计 ...

  6. C语言 HTTP上传文件-利用libcurl库上传文件

    原文  http://justwinit.cn/post/7626/ 通常情况下,一般很少使用C语言来直接上传文件,但是遇到使用C语言编程实现文件上传时,该怎么做呢? 借助开源的libcurl库,我们 ...

  7. IPTABLES 映射问题

    今天要做一个新的映射:将内网的一个8090口映射到外网的8087口. 在 /ETC/RC.LOCAL中最后插入: iptables -t nat -A PREROUTING -d outIP -p t ...

  8. 指尖上的电商---(2)Solr全文搜索引擎的准备工作

    Solr是一个基于Lucene的全文搜索引擎.提供了更丰富的搜索语言.更灵活的配置.更高的查询效率. 一句话.与Lucene相比.有过之而无不及.这一节里, 主要谈论两个知识点:Jdk的安装和Tomc ...

  9. openstack之网络基础

    L1:物理层L2:数据链路层,基于mac地址的通信,通过交换机连接:对等传输,即交换机上的一个主机发一个包,连接在该交换机上的所有机器都能收到:L3:网络层,基于ip地址,路由器设备,连接不同网段,进 ...

  10. JavaScript 高级程序设计(第3版)笔记——chapter7:函数表达式

    一.函数表达式的语法形式 匿名函数 var functionName = function(arg0, arg1, arg2) { //函数体 } 二.函数表达式没有函数提升 var a = 1; i ...