TOJ1337 Snakes

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?

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.

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

Output for Sample Input

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



Source: Waterloo Local Contest Jan. 29, 2000

 

这道题的意思是一个平面上有1000*1000的矩形和很多圆形,看能否从矩形左边出发,不出矩形边界且不接触任何圆形能到达矩形右边。

起初一脸茫然,后来学习了一种新方法----并查集。

#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
struct snake{
    double x,y,r;
}a[1020];
int set[1020];//并查集集合 
int find(int i){//并查集查找 
    int r = i;
    while(r!=set[r])
        r = set[r];
    return r;
} 
void join(int i,int j){//并查集合并 
    int b=find(i), c=find(j);
    if(b!=c)
        set[b] = c;
}
int main(){
    int n,i,j,k;
    scanf("%d",&n);
    for(i=0;i<=n;i++)    set[i] = i;
    set[1010] = 1010;
    for(i=1;i<=n;i++){
        scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r);
        for(j=1;j<i;j++){//两蛇攻击范围相交 
            if( (a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)<(a[i].r+a[j].r)*(a[i].r+a[j].r) ){
                join(j,i);
            }     
        }
        if(a[i].y<a[i].r){//该蛇攻击范围与下边界相交
            join(1010,i);
        }
        if(a[i].y+a[i].r>1000){
            join(0,i);
        }
    }
    if(find(0)==find(1010))//上下边界之间被蛇攻击范围覆盖 
        printf("Bill will be bitten.\n");
    else{
        double sy=1000.0,ey=1000.0;
        for(i=1;i<=n;i++){
            if(find(i)==find(0) && a[i].x<a[i].r && a[i].y-sqrt(a[i].r*a[i].r-a[i].x*a[i].x)<sy){
                sy = a[i].y-sqrt(a[i].r*a[i].r-a[i].x*a[i].x);
            }
            if(find(i)==find(0) && 1000-a[i].x<a[i].r && a[i].y-sqrt(a[i].r*a[i].r-(1000-a[i].x)*(1000-a[i].x))<ey){
                ey = a[i].y-sqrt(a[i].r*a[i].r-(1000-a[i].x)*(1000-a[i].x));
            }
        }
        printf("Bill enters at (0.00, %.2f) and leaves at (1000.00, %.2f).\n",sy,ey);
    }
    return 0;
}

 

posted @ 2017-02-07 14:35  DGSX  阅读(352)  评论(0编辑  收藏  举报