You are playingpaintball on a 1000x1000 square field. A number of your opponents are on thefield hiding behind trees at various positions. Each opponent can fire apaintball a certain distance in any direction. Can you cross the field withoutbeing hit by a paintball?
Assume that thesouthwest corner of the field is at (0,0) and the northwest corner at (0,1000).
InputSpecification
The input containsseveral scenario. Each scenario consists of a line containing n <= 1000, thenumber of opponents. A line follows for each opponent, containing three realnumbers: the (x,y) location of the opponent and its firing range. The opponentcan hit you with a paintball if you ever pass within his firing range.
You must enter thefield somewhere between the southwest and northwest corner and must leavesomewhere between the southeast and northeast corners.
OutputSpecification
For each scenario,if you can complete the trip, output four real numbers with two digits afterthe 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 themost northerly. If there is no such pair of positions, print the line:
IMPOSSIBLE
Sample Input
500 500 499
0 0 999
1000 1000 200
Output forSample Input
0.00 1000.001000.00 800.00
代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
using namespacestd;
const int maxn =1000 + 5;
const double W =1000.00;
int n, vis[maxn];
double x[maxn],y[maxn], r[maxn], Left, Right;
bool ok;
bool intersect(intc1, int c2)
{
return sqrt((x[c1]-x[c2])*(x[c1]-x[c2]) +(y[c1]-y[c2])*(y[c1]-y[c2])) < r[c1] + r[c2];
}
voidcheck_circle(int u)
/*
注意该函数的前提是:下标为u的圆最上部超过了场地的上边界或者
下标为u的圆与最上部超过了场地上边界的圆相交
*/
{
if(x[u] - r[u] < 0)
{
Left = min(Left, y[u] - sqrt(r[u]*r[u]- x[u]*x[u]));
}
if(x[u] + r[u] > W)
{
Right = min(Right, y[u] -sqrt(r[u]*r[u] - (W-x[u])*(W-x[u])));
}
}
bool dfs(int u)//u是圆形的输入编号,能达到底部则返回true
{
if(vis[u])//如果已经访问过,直接返回
{
return false;
}
vis[u] = 1;//标记已访问
if(y[u] - r[u] <= 0)//若该圆上下贯通,则无法通过场地
{
return true;
}
for(int v = 0; v < n; v++)//遍历其余的所有圆形
{
if(intersect(u, v) && dfs(v))
//若存在其他的圆形与该圆形相交,不包括相切,则对另一个圆深搜
{
return true;//多圆相连,上下贯通
}
}
check_circle(u);//目标线路可能存在,更新最北的位置
return false;
}
int main()
{
while(cin>>n)
{
ok = true;
Left = Right = W;
memset(vis, 0, sizeof(vis));//每组数据的访问标记都要清空
for(int i = 0; i < n; i++)
{
cin>>x[i]>>y[i]>>r[i];
}
for(int i = 0; i < n; i++)//遍历每一个圆形
{
if(y[i] + r[i] >= W&&dfs(i))
/*
充分利用‘&&’短路的特性,因为题目要求出最北边(最上面的)的坐标,
因此,如果该圆形没有越过最上边界的可能,那么该圆形不可能阻挡目标线路
即没有必要再对该圆形进行深搜
*/
{
ok = false; // 从上往下dfs
break;
}
}
if(ok)
{
cout<<"0.00"<<fixed<<setprecision(2)<<""<<Left<<" "<< W<<""<<Right<<endl;
}
else
{
cout<<"IMPOSSIBLE\n";
}
}
return 0;
}