[dfs]11853 - Paintball

You are playing paintball on a 1000 1000 square eld. A
number of your opponents are on the eld hiding behind trees
at various positions. Each opponent can re a paintball a
certain distance in any direction. Can you cross the eld
without being hit by a paintball?
Assume that the southwest corner of the eld 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 ring range. The
opponent can hit you with a paintball if you ever pass within
his ring range.
You must enter the eld 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 eld, 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 Output
0.00 1000.00 1000.00 800.00

把每个敌人看出一个圆,从上往下跑连通即可

写完这题,感觉结构体虽然内聚性高,但是不够灵活

#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\n",left,right);
      else printf("IMPOSSIBLE\n");
   }
   return 0;
}
时间: 2024-10-10 04:34:54

[dfs]11853 - Paintball的相关文章

UVA 11853 - Paintball(dfs)

UVA 11853 - Paintball 题目链接 题意:就是给定一些圆,判断能否不经过这些圆从左边走到右边,如果可以要求起始和终止位置尽量往北,输出位置 思路:每次找一个超出上边界的圆dfs,如果能到下边界,就是隔断了肯定到达不了,如果隔断左右边界,就要更新答案的值 代码: #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algor

[UVA 11853]Paintball[DFS]

题目链接:[UVA 11853]Paintball[DFS] 题意分析: 在一个1000*1000的方块场地中,你需要从最左边开始一路避开敌人的攻击到达最右边.敌人有自己的坐标以及攻击范围,也就是一个圆形范围内你都不能碰到,问你能到达最右边吗?能的话输出左边进入的最大坐标(0,Ymax), 右边出去的最大坐标(1000,Ymax). 解题思路: 什么情况下不能到达目标呢?只有这种情况,也就是相邻的圆连接起来隔断了整个地图,否则都是可以到达的.这样的话,一个dfs直接判断就行了.剩下的是坐标怎么找

UVA 11853 Paintball ——(dfs+圆交判定)

题意:给出一个1000*1000大小的矩阵,里面有若干圆,表示障碍物,现在要找出从左边到右边的一条通路,输出入口和出口的坐标,如果有多答案,输出y值最大的答案. 分析:从与上面相连的圆开始dfs,每次找与之相交的圆作为dfs的路径,如果能访问到下面,那么左边和右边肯定是不连通的:否则,连通.并且在dfs的时候更新y值最大的答案. 具体见代码: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h>

uva 11853 Paintball dfs找连通块

题意: 给出一个矩形湖, 湖里面有一些圆形地小岛, 问能否从左岸乘船到达右岸,如果能,找出最上面的起点和终点. 题解: 如果能从左岸到达右岸,那么一定不能存在一个连通的岛屿从上岸连到下岸, 所以直接从上到下做dfs,判断是否存在从上岸到下岸地连通块,完成判断.那么接下来就是如何找出最上方地点了,画画图便发现,对于起点,如果存在跨越上岸和左岸地连通岛屿,那么起点一定只能在左岸地交点下方,所以,只需在dfs的过程中更新起点和终点位置即可. 代码: #include <queue> #include

【DFS】Paintball(6-22)

[UVA11853]Paintball 算法入门经典第6章6-22(P175) 题目大意:有一个1000*1000的正方形战场,西南角坐标(0,0),西北角坐标(0,1000),有n个敌人,每个敌人处在(xi,yi),攻击范围为ri,要避开他们的攻击范围,求从最左边出发的最北边出发点及右边的最北边到达点. 试题分析:我们先判断是否能有方案,如何判断?将相交圆的圆心相连,看从交上边界的圆出发是否能到达与下边界相交的圆.然后再这个过程中如果看到与左/右边界相交的圆那么更新答案就好了. #includ

UVA 11853 [dfs乱搞]

/* 大连热身E题 不要低头,不要放弃,不要气馁,不要慌张 题意: 在1000×1000的格子内有很多个炮弹中心,半径给定. 为某人能否从西部边界出发,从东部边界走出. 不能输出不能,能的话输出最北边的入口和出口的坐标. 思路: dfs乱搞题.把炮弹辐射范围连在一起的炮弹看作一个整体,记录下它围起来的边界区域. 然后找到最北边的输出. */ #include<bits/stdc++.h> using namespace std; double x[1005],y[1005],r[1005];

解救小哈——DFS算法举例

一.问题引入 有一天,小哈一个人去玩迷宫.但是方向感不好的小哈很快就迷路了.小哼得知后便去解救无助的小哈.此时的小哼已经弄清楚了迷宫的地图,现在小哼要以最快的速度去解救小哈.那么,问题来了... 二.问题的分析 首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q).其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径. 此时摆在小哼面前的路有两条,我们可以先让小哼往右边走,直到走不通的时候再回到这里,再去尝试另外一个方向. 在这里我们规定一

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

uva1103(dfs)

UVA - 1103 还是没写好,,看的别人的 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <cstdlib> 7 #include <stack> 8 #include <cctype> 9 #include <str