UVA 11853

题意:有n个敌人,每个敌人有一个攻击范围,问你是否存在从西边到东边的路径,如果存在,输出入点和出点最靠北的坐标。

把每个敌人看出一个圆,从上往下跑dfs连通,如果到达底部,那么无解。要求出最靠北的坐标,就在dfs过程中沿途检查与边界相交的点,并更新边界坐标。

#include<cstdio>
#include<cstring>
//#include<vector>
//#include<queue>
#include<algorithm>
#include<math.h>
//#define local
using namespace std;

const int maxn = 1000 + 1;
const double W = 1000;

int x[maxn], y[maxn], r[maxn];
int n;
double left,right;

bool intersect(int a,int b) {
   return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])) < r[a]+r[b];
}
void check(int u)
{
   if(x[u] < r[u]) 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]) ) ) ;
}
int vis[maxn];
//top to bottom
bool dfs(int u)
{
   if(vis[u]) return false;
   vis[u] = 1;
   if(y[u] < r[u]) return true;
   for(int v = 0; v < n; v++){
      if(intersect(u,v) && dfs(v)) return true;
   }
   check(u);
   return false;
}


int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
#endif // local
   while(~scanf("%d",&n)) {
      bool ok = true;
      memset(vis,0,sizeof(vis));
      left = right = W;
      for(int i = 0; i < n; i ++){
         scanf("%d%d%d",x+i,y+i,r+i);
      }
      for(int i = 0; i < n; i ++) {
         if(r[i]+y[i]>=W && dfs(i)) {ok = false; break;}
      }
      if(ok) printf("0.00 %.2lf 1000.00 %.2lf
",left,right);
      else printf("IMPOSSIBLE
");
   }
   return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4601283.html