zoukankan      html  css  js  c++  java
  • [POJ 2588]--Snakes(并查集)

    题目链接: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],这肯定不能到达,
         否则的话,通过判断左右边界与蛇攻击区域的相交关系,判断边界是否可行,可行的话,在此过程中找出最北方的点,具体见代码注释分析~~~
     
    代码如下:
      1 #include<iostream>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<cstdio>
      5 using namespace std;
      6 #define maxn 1005
      7  
      8 /*-------------上下左右边界判断-------------*/
      9 struct UpDown{
     10     double x, y, area;
     11 }snack[maxn];
     12 struct LeftRight{
     13     double up, down;
     14     int i;
     15 }le[maxn], ri[maxn];
     16  
     17  
     18 int father[maxn], map[maxn][maxn];
     19  
     20  
     21 //----------检查当前出入最高点是否可用--------------------
     22 bool check(LeftRight *p, double x, int n){
     23     for (int i = 0; i < n; i++){
     24         if (p[i].up>x&&p[i].down < x)
     25             return false;
     26     }
     27     return true;
     28 }
     29  
     30 //-------------并查集判断构造的点(包括上下边界)是否连通-------------------
     31 int getf(int x){
     32     return father[x] != x ? father[x] = getf(father[x]) : x;
     33 }
     34  
     35  
     36 int main()
     37 {
     38     int n, i, j;
     39     while (cin >> n){
     40         for (i = 0; i <= n + 1; i++)
     41             father[i] = i;
     42         int L = 0, R = 0;
     43         memset(map, 0, sizeof(map));
     44         for (i = 1; i <= n; i++){
     45             cin >> snack[i].x >> snack[i].y >> snack[i].area;
     46  
     47             //-----------建立上下关系---------------
     48             if (snack[i].y + snack[i].area > 1000)
     49                 map[0][i] = map[i][0] = 1;
     50             if (snack[i].y - snack[i].area < 0)
     51                 map[n + 1][i] = map[i][n + 1] = 1;
     52  
     53             //---------建立左右关系------------------
     54             if (snack[i].x - snack[i].area < 0){
     55                 le[L].up = snack[i].y + sqrt(pow(snack[i].area, 2) - pow(snack[i].x, 2));
     56                 le[L].down = snack[i].y - sqrt(pow(snack[i].area, 2) - pow(snack[i].x, 2));
     57                 le[L++].i = i;
     58             }
     59             if (snack[i].x + snack[i].area >1000){
     60                 ri[R].up = snack[i].y + sqrt(pow(snack[i].area, 2) - pow((1000 - snack[i].x), 2));
     61                 ri[R].down = snack[i].y - sqrt(pow(snack[i].area, 2) - pow((1000 - snack[i].x), 2));
     62                 ri[R++].i = i;
     63             }
     64         }
     65  
     66         //-------------通过圆心判断各区域相交情况-------------------
     67         for (i = 1; i < n; i++)
     68         for (j = i + 1; j <= n; j++){
     69             if (snack[i].area + snack[j].area>sqrt(pow((snack[i].x - snack[j].x), 2) + pow((snack[i].y - snack[j].y), 2)))
     70                 map[i][j] = map[j][i] = 1;
     71         }
     72  
     73         //-----------并查集处理------------------
     74         for (i = 0; i <= n; i++)
     75         for (j = i + 1; j <= n + 1; j++){
     76             if (map[i][j]){
     77                 int x = getf(i), y = getf(j);
     78                 if (x != y)
     79                     father[y] = x;
     80             }
     81         }
     82  
     83  
     84  
     85         if (getf(n + 1) == getf(0))
     86             cout << "Bill will be bitten." << endl;
     87  
     88         else{
     89             double Lflag = -1, Rflag = -1, Lup = 1000, Ldown = 0, Rup = 1000, Rdown = 0;
     90  
     91             //-----------找到最高可用左边界------------------------
     92             for (i = 0; i < L; i++){
     93                 if (getf(le[i].i) == getf(0) && le[i].down < Lup)
     94                     Lup = le[i].down;
     95                 if (getf(le[i].i) == getf(n + 1) && le[i].up >Ldown)
     96                     Ldown = le[i].up;
     97             }
     98  
     99             if (check(le, 1000, L) && Lup == 1000)
    100                 Lflag = 1000;
    101  
    102             for (i = 0; i < L; i++){
    103                 if (le[i].up <= Lup&&le[i].up >= Ldown&&check(le, le[i].up, L) && Lflag < le[i].up)
    104                     Lflag = le[i].up;
    105                 if (le[i].down <= Lup&&le[i].down >= Ldown&&check(le, le[i].down, L) && Lflag < le[i].down)
    106                     Lflag = le[i].down;
    107             }
    108             //----------------------------------------------------------------------
    109  
    110  
    111             //--------------------------===右边界处理-----------------------
    112             for (i = 0; i < R; i++){
    113                 if (getf(ri[i].i) == getf(0) && ri[i].down < Rup)
    114                     Rup = ri[i].down;
    115                 if (getf(ri[i].i) == getf(n + 1) && ri[i].up >Rdown)
    116                     Rdown = ri[i].up;
    117             }
    118             if (check(ri, 1000, R) && Rup == 1000)
    119                 Rflag = 1000;
    120             for (i = 0; i < R; i++){
    121                 if (ri[i].up <= Rup&&ri[i].up >= Rdown&&check(ri, ri[i].up, R) && Rflag < ri[i].up)
    122                     Rflag = ri[i].up;
    123                 if (ri[i].down <= Rup&&ri[i].down >= Rdown&&check(ri, ri[i].down, R) && Rflag < ri[i].down)
    124                     Rflag = ri[i].down;
    125             }
    126             if (L == 0)
    127                 Lflag = 1000;
    128             if (R == 0)
    129                 Rflag = 1000;
    130             if (Rflag < 0 || Lflag < 0)
    131                 cout << "Bill will be bitten." << endl;
    132             else
    133                 printf("Bill enters at (0.00, %.2lf) and leaves at (1000.00, %.2lf).
    ", Lflag, Rflag);
    134         }
    135     }
    136     return 0;
    137 }
    View Code
     
  • 相关阅读:
    Angular7 表单
    使用Angular2的Http发送AJAX请求
    Nginx配置SSL证书实现https访问「浏览器未认证」
    详解 Nginx如何配置Web服务器
    前后端分离不可缺少的神器 NGINX
    程序员的快速开发框架:Github上 10 大优秀的开源后台控制面板
    腾讯出品的一个超棒的 Android UI 库
    Vue 旅游网首页开发1-工具安装及码云使用
    Angular routing生成路由和路由的跳转
    Angular 父子组件传值
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4581022.html
Copyright © 2011-2022 走看看