UVa 11853 PaintBall

圆圈迷宫路径搜索

思路:首先把每个圆的与它相连的圆找到,然后找到与上边界相交的圆,从上边界的圆开始BFS,如果遇到了下边界,那么输出IMPOSSIBLE,如果可以的话,记录途中遇到的左边界的点的Y值和右边界的Y值.

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <list>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <cctype>
#include <cmath>
#include <cstring>
#include <climits>
#include <complex>
#include <set>
#include <deque>
#define DEBUG(x) cerr<<"line:"<<__LINE__<<", "<<#x" == "<<(x)<<endl;
#define REP(i,s,n) for(int i=(int)(s);i<(int)(n);i++)
#define FOR(it,s) for(__typeof(s.begin()) it=s.begin();it!=s.end();it++)
#define ALL(a) (a).begin(),(a).end()
#define RALL(x) (a).rbegin(),(a).rend()
#define RI(x) scanf("%d",&(x))
#define RII(x,y) scanf("%d%d",&(x),&(y))
#define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define DRI(x) int (x);scanf("%d",&(x))
#define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
#define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
#define MS0(a) memset((a),0,sizeof((a)))
#define MS1(a) memset((a),-1,sizeof((a)))
#define MS(a,b) memset((a),(b),sizeof((a)))
#define PB push_back
#define SZ(a) (int)(a).size()

using namespace std;

typedef long long LL;
typedef unsigned int uint;
typedef unsigned long long ULL;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef vector<vi> vvi;

#define INF 1000000000
const double eps = 1e-10;
int dcmp(double x){
  if(fabs(x) < eps) return 0;
  else return x < 0 ? -1 : 1;
}
// ------------------
// author : onehrxn
// ------------------
const int maxn = 1000 + 5;
const int TOP = 1000;
const int RIGHT = 1000;
int x[maxn], y[maxn], r[maxn];
vector<int> g[maxn];
bool vis[maxn];
int N;
vector<int> up;
void init(int N);
inline double dis(int a ,int b);
inline bool pinter(int a, int b);
inline bool inter(int p, int dir); // up 0 left 1 down 2 right 3
bool solve(double &ly, double &ry); // return if can be solved and the ans
int main(void)
{
  //ios::sync_with_stdio(false);
  //cin.tie(0);
#ifdef LOCAL
  //freopen("input", "r", stdin);
  //freopen("output", "w", stdout);
#endif
  while(~RI(N)){
    init(N);
    for(int i = 0; i < N; i++){
      RIII(x[i], y[i], r[i]);
    }
    for(int i = 0; i < N; i++){
      if(inter(i, 0)) up.PB(i);
      for(int j = i + 1; j < N; j++)
        if(pinter(i,j)){
          g[i].PB(j); g[j].PB(i);
        }
    }
    double ly, ry;
    if(solve(ly, ry)) {
      printf("%.2lf %.2lf %.2lf %.2lf\n", 0.0, ly, 1000.0, ry);
    }
    else printf("IMPOSSIBLE\n");
  }
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
  return 0;
}

void init(int N){
  up.clear();
  for(int i = 0; i < N; i++){
    vis[i] = 0;
    g[i].clear();
  }
}

inline bool pinter(int a, int b){
  if(dcmp(dis(a,b) - r[a] - r[b]) <= 0) return 1;
  return 0;
}

inline double dis(int a, int b){
  return sqrt( (x[b] - x[a])*(x[b] - x[a]) + (y[b] - y[a])*(y[b] - y[a]));
}
inline bool inter(int p, int dir){
  switch(dir){
  case 0: return ((TOP - y[p]) <= r[p]);
  case 1: return ((x[p]) <= r[p]);
  case 2: return (y[p] <= r[p]);
  case 3: return (RIGHT - x[p] <= r[p]);
  }
  return 0;
}

bool solve(double &ly, double &ry){
  MS0(vis);
  queue<int> q;
  ly = 1000.0;
  ry = 1000.0;
  FOR(it, up) q.push(*it);
  while(!q.empty()){
    int now = q.front(); q.pop();
    vis[now] = 1;
    if(inter(now, 2)) return 0;
    if(inter(now, 1)){
      // update the ly
      double diffx = x[now] * 1.0;
      double tmpy = y[now]*1.0 - (sqrt(r[now]*r[now]*1.0 - diffx*diffx));
      if(dcmp(tmpy - ly) < 0) ly = tmpy;
    }
    if(inter(now, 3)){
      // update the ry
      double diffx = RIGHT*1.0 - x[now];
      double tmpy = y[now]*1.0 - (sqrt(r[now]*r[now]*1.0 - diffx*diffx));
      if(dcmp(tmpy - ry) < 0) ry = tmpy;
    }
    for(int i = 0; i < g[now].size(); i++) {
      if(!vis[g[now][i]]) q.push(g[now][i]);
    }
  }
  return 1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值