ZCMU—1792

Problem C: Problem C - Snakes

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 5  Solved: 3
[Submit][Status][Web Board]

Description

Problem C - 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."

Input

Output

Sample Input

3500 500 4990 0 9991000 1000 200

Sample Output

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

【分析】

题目难懂...题意是给你很多个蛇的攻击范围,以x,y,为圆心,半径为r,问你一个人从场地西边进,能不能从东边出去。

题意弄懂之后就会发现题目内容其实很简单,就是给你n个圆,问你有没有相交的圆能把上边界和下边界连起来。

考虑并查集,相交的圆属于同一个堆,最后判断上边界和下边界是否相连就可以了,但是这里有一点挺麻烦的就是如何判断入点和出点,题目里要求说入点和出点都要小,所以去判断一下每个堆的点与西边和东边相交的位置,求个最小的就可以了。题意很简单。。写起来挺复杂的其实。。。poj上我WA了7次才ac。。大概是我数学水平太差...

【代码】

#include <stdio.h>  
#include <math.h>  
#include <algorithm>
using namespace std;
struct xx{  
    double x,y,r;  
}a[2000];
int f[2000];  
int find(int x)  
{  
    if (f[x]==x) return x;
    return f[x]=find(f[x]);  
}  
int main()  
{  
    int n;scanf("%d",&n);  
    for (int i=0;i<=n;i++) f[i]=i;  
    f[1111]=1111;
    for (int i=1;i<=n;i++)  
    {  
        scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r);  
        for (int j=1;j<i;j++)
            if (sqrt((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<=0) 
                f[find(j)]=find(i);
        if (fabs(a[i].y)-a[i].r<0) f[find(1111)]=f[find(i)];  
        if (fabs(fabs(a[i].y)-1000)-a[i].r<0) f[find(i)]=f[find(0)];  
    }  
    if (find(1111)==find(0)) printf("Bill will be bitten.");  
    else
    {
        double start=1000,end=1000;  
        for (int i=1;i<=n;i++)  
        {  
            double d=fabs(a[i].x-1000);  
            if (a[i].x-a[i].r<0 && find(i)==find(0) && a[i].y-sqrt(a[i].r*a[i].r-a[i].x*a[i].x)<start) start=a[i].y-sqrt(a[i].r*a[i].r-a[i].x*a[i].x);  
            if (d-a[i].r<0 && find(i)==find(0) && a[i].y-sqrt(a[i].r*a[i].r-d*d)<end) end=a[i].y-sqrt(a[i].r*a[i].r-d*d);  
        }  
        printf("Bill enters at (0.00, %0.2f) and leaves at (1000.00, %0.2f).",start,end);    
    }
    return 0;  
}  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值