博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UVA11853-Paintball(对偶图)
阅读量:5013 次
发布时间:2019-06-12

本文共 3463 字,大约阅读时间需要 11 分钟。

Problem UVA11853-Paintball

Accept:229  Submit:1830

Time Limit: 3000 mSec

Problem Description

 

You are playing paintball on a 1000×1000 square field. A number of your opponents are on the field hiding behind trees at various positions. Each opponent can fire a paintball a certain distance in any direction. Can you cross the field without being hit by a paintball? Assume that the southwest corner of the field is at (0,0) and the northwest corner at (0,1000).

 

 Input

The input contains several scenario. Each scenario consists of a line containing n ≤ 1000, the number of opponents. A line follows for each opponent, containing three real numbers: the (x,y) location of the opponent and its firing range. The opponent can hit you with a paintball if you ever pass within his firing range. You must enter the field somewhere between the southwest and northwest corner and must leave somewhere between the southeast and northeast corners.

 

 Output

For each scenario, if you can complete the trip, output four real numbers with two digits after the decimal place, the coordinates at which you may enter and leave the field, separated by spaces. If you can enter and leave at several places, give the most northerly. If there is no such pair of positions, print the line:‘IMPOSSIBLE’

 

 Sample Input

3
500 500 499
0 0 999
1000 1000 200
 
 

 Sample Ouput

0.00 1000.00 1000.00 800.00

 

题解:这个题思路比较奇特,有了对偶图的思路,这个题就基本上是个水题了。题目问的时能过去,反过来考虑,怎样不能过去。把正方形区域想象成湖,各个士兵形成的攻击范围看作一个个踏板,如果能够从上边界走到下边界,那么整个图就被分成了左右两部分,自然不能从左到右。并且这个条件时充要的,因此可以作为判据。之后就是如何找最北边。只看左边,如果某个踏板从上边界的踏板出发不能够到达,那该踏板就不对入口坐标造成影响,反过来,如果能到达,并且该踏板和左边界右交点,那么沿着它的上交点就能走回上边界,相当于左上角这一块被包围了,自然入口在下面,据此得到结论,只需要找出从上边界出发能到达的圆,计算出这些圆和左边界交点的最小值就是最北的入口,右边界同理。

 

1 #include 
2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 const int maxn = 1000+5; 8 const double wide = 1000.0; 9 10 struct Point{11 double x,y,r;12 }point[maxn];13 14 bool intersection(Point &a,Point &b){15 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)) <= a.r+b.r;16 }17 18 int n;19 bool vis[maxn];20 double Left,Right;21 22 void check_circle(int a){23 if(point[a].x-point[a].r < 0) Left = min(Left,point[a].y-sqrt(point[a].r*point[a].r-point[a].x*point[a].x));24 if(point[a].x+point[a].r > wide) Right = min(Right,point[a].y-sqrt(point[a].r*point[a].r-(wide-point[a].x)*(wide-point[a].x)));25 }26 27 bool dfs(int u){28 if(vis[u]) return false;29 vis[u] = true;30 if(point[u].y-point[u].r < 0) return true;31 for(int v = 1;v <= n;v++){32 if(v==u || vis[v]) continue;33 if(intersection(point[u],point[v]) && dfs(v)) return true;34 }35 check_circle(u);36 return false;37 }38 39 int main()40 {41 //freopen("input.txt","r",stdin);42 while(~scanf("%d",&n)){43 memset(vis,false,sizeof(vis));44 Left = Right = wide;45 for(int i = 1;i <= n;i++){46 scanf("%lf%lf%lf",&point[i].x,&point[i].y,&point[i].r);47 }48 bool ok = true;49 for(int i = 1;i <= n;i++){50 if(!vis[i] && point[i].y+point[i].r>=wide && dfs(i)){51 ok = false;52 break;53 }54 }55 if(ok) printf("%.2f %.2f %.2f %.2f\n",0.000,Left,wide,Right);56 else printf("IMPOSSIBLE\n");57 }58 return 0;59 }

 

转载于:https://www.cnblogs.com/npugen/p/9520797.html

你可能感兴趣的文章
leetcode : Count and Say [基本功]
查看>>
洛谷 P2485 [SDOI2011]计算器 解题报告
查看>>
c#访问存储过程
查看>>
Slickflow.NET 开源工作流引擎基础介绍(三) -- 基于HTML5/Bootstrap的Web流程设计器
查看>>
Node教程
查看>>
java将字段映射成另一个字段,关于 接口传参 字段不对应转换
查看>>
Redis
查看>>
字段和属性的区别
查看>>
HTTP(一)工作机制
查看>>
条形码扫描枪数据读取的问题
查看>>
$this->autoRender = false
查看>>
健壮的 Java 基准测试
查看>>
phpstorm查看类的继承关系
查看>>
git create clone(仓库)
查看>>
chmod修改文件权限的命令
查看>>
新博客牵至简书
查看>>
矩阵求逆
查看>>
在 Windows 8、Windows 10 桌面模式下的 .NET Framework 程序中,引用 Windows.Runtime 的 API。...
查看>>
2015 8月24号 工作计划与实行
查看>>
MVC AJAX
查看>>