UVALive 4035 - Undetectable Tour(并查集)

题意:给定一个 N * N(3 <= N <= 10000)的矩形区域,左下角为(0,0),右上角为(N,N),现在要从左下角走到右上角,但是有 k(k <= 100)个监视器,每个监视器的监视范围都是统一的,现给定监视范围可能出现的种类与概率,求能够逃出去的概率。(计算距离时均用曼哈顿距离)

1、若两个监视器的距离 <= 两个监视器的监视范围之和,则这两个监视器间的路就不可走;

2、若监视器距离墙的距离 <= 监视器的监视范围,则监视器与墙之间就不可走;

综上,对于每一个监视范围,可以借助并查集判断是否 "左边界和上边界" 与 "右边界和下边界" 之间不可走,若可走则证明在此监视范围下可以逃出去。

若将监视范围排序,并二分找临界答案,时间将更短。

代码如下:

  1 #pragma comment(linker, "/STACK:102400000, 102400000")
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cctype>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<iostream>
  8 #include<sstream>
  9 #include<iterator>
 10 #include<algorithm>
 11 #include<string>
 12 #include<vector>
 13 #include<set>
 14 #include<map>
 15 #include<deque>
 16 #include<queue>
 17 #include<stack>
 18 #include<list>
 19 #define fin freopen("in.txt", "r", stdin)
 20 #define fout freopen("out.txt", "w", stdout)
 21 #define pr(x) cout << #x << " : " << x << "   "
 22 #define prln(x) cout << #x << " : " << x << endl
 23 #define Min(a, b) ((a < b) ? a : b)
 24 #define Max(a, b) ((a < b) ? b : a)
 25 typedef long long ll;
 26 typedef unsigned long long llu;
 27 const int INT_INF = 0x3f3f3f3f;
 28 const int INT_M_INF = 0x7f7f7f7f;
 29 const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
 30 const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
 31 const double pi = acos(-1.0);
 32 const double EPS = 1e-8;
 33 const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
 34 const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
 35 const ll MOD = 1e9 + 7;
 36 using namespace std;
 37
 38 #define NDEBUG
 39 #include<cassert>
 40 const int MAXN = 100 + 10;
 41 const int MAXT = 10000 + 10;
 42
 43 struct Detector{
 44     int x, y;
 45     Detector(int xx = 0.0, int yy = 0.0) : x(xx), y(yy) {}
 46 };
 47
 48 struct Query{
 49     int radius;
 50     double pro;
 51     bool operator < (const Query &rhs) const{
 52         return radius < rhs.radius;
 53     }
 54 }q[MAXN];
 55
 56 int T, m, fa[MAXN * 3], n;
 57 vector<Detector> vec;
 58
 59 int Find(int x) {
 60     return fa[x] = (fa[x] == x) ? x : Find(fa[x]);
 61 }
 62
 63 inline int get_dist(int x1, int y1, int x2, int y2) {
 64     return abs(x1 - x2) + abs(y1 - y2);
 65 }
 66
 67 inline void merge_(int x, int y) {
 68     int one = Find(x), two = Find(y);
 69     if(one == two)  return;
 70     if(one < two)  fa[two] = one;
 71     else  fa[one] = two;
 72 }
 73
 74 bool judge(int dist) {
 75     for(int i = 0; i < MAXN * 3; ++i)  fa[i] = i;
 76     int len = (int)vec.size() - 1;
 77     for(int i = 1; i <= len; ++i)
 78         for(int j = i + 1; j <= len; ++j) {
 79             int tmp = get_dist(vec[i].x, vec[i].y, vec[j].x, vec[j].y);
 80             if(tmp <= dist * 2)  merge_(i, j);
 81         }
 82     for(int i = 1; i <= len; ++i) {
 83         if(vec[i].x <= dist || n - vec[i].y <= dist)  merge_(0, i);
 84         if(vec[i].y <= dist || n - vec[i].x <= dist)  merge_(i, len + 1);
 85     }
 86     return Find(0) != Find(len + 1);
 87 }
 88
 89 int solve() {
 90     int l = 0, r = m - 1;
 91     while(l < r) {
 92         int mid = l + (r - l + 1) / 2;
 93         if(judge(q[mid].radius))  l = mid;
 94         else  r = mid - 1;
 95     }
 96     return judge(q[l].radius) ? l : -1;
 97 }
 98
 99 int main(){
100 //    fin;
101     scanf("%d", &T);
102     while(T--) {
103         vec.clear();
104         vec.push_back(Detector());
105         scanf("%d%d", &n, &m);
106         for(int i = 0; i < m; ++i)  scanf("%d%lf", &q[i].radius, &q[i].pro);
107         sort(q, q + m);
108         int u, v;
109         while(scanf("%d", &u) == 1 && u != -1) {
110             scanf("%d", &v);
111             vec.push_back(Detector(u, v));
112         }
113         int len = solve();
114         double ans = 0.0;
115         for(int i = 0; i <= len; ++i)  ans += q[i].pro;
116         printf("%g\n", ans);
117     }
118     return 0;
119 }
时间: 2024-10-06 13:55:54

UVALive 4035 - Undetectable Tour(并查集)的相关文章

UVALive 4487 Exclusive-OR 加权并查集神题

已知有 x[0-(n-1)],但是不知道具体的值,题目给定的信息 只有 I P V,说明 Xp=V,或者 I P Q V,说明 Xp ^ Xq=v,然后要求回答每个询问,询问的是 某任意的序列值 Xp1^Xp2,,,,X^pk 这个题目用加权并查集是这么处理的: 1. f[]照样是代表父节点,照样进行路径压缩,把每个 V[i]=V[i]^V[f[i]],即节点存储的值实际是它与它父亲的异或的值.为什么要这样呢,因为异或首先满足交换律,而且异或同一个数偶数次,即相当于本身,那么这个题目的其中一个要

UVALive 4730 线段树+并查集

点击打开链接 题意:在坐标上给n个点,r的操作是将两个点连起来,l的操作是问你y=u的这条线连接的集合块数和这些集合内的点的个数 思路:很麻烦的一道题,在网上看了题意和做法后,开始了一下午的调bug过程,做法很好懂,我开了两个线段树,一个维护点代表的直线的集合个数,另一个则是路过集合内的点的个数,然后集合的判断直接用并查集就行了,这是两个核心,然后就是自己瞎写的了,代码丑的可以而且好像除了本人别人看着可能要骂人了,有兴趣研究的可以留言我来解答,那难的部分其实就是并查集合并时该怎么将这两个要维护的

UVALive - 3644 - X-Plosives (并查集!!)

X-Plosives A secret service developed a new kind of explosive that attain its volatile property only when a specific association of products occurs. Each product is a mix of two different simple compounds, to which we call a binding pair. If N>2, the

UVALive 6091 - Trees (并查集)

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4102 ----------------------------------------------------------------------------------------------------------------------------------

UVALive 4730 Kingdom 线段树+并查集

题目链接:点击打开链接 题意见白书P248 思路: 先把读入的y值都扩大2倍变成整数 然后离散化一下 用线段树来维护y轴 区间上每个点的 城市数量和联通块数量, 然后用并查集维护每个联通块及联通块的最大最小y值,还要加并查集的秩来记录每个联通块的点数 然后就是模拟搞.. T^T绝杀失败题..似乎数组开小了一点就过了,== #include<stdio.h> #include<math.h> #include<vector> #include<string.h>

UVALive - 3644X-Plosives(并查集)

题目:UVALive - 3644X-Plosives(并查集) 题目大意:给出K个简单的化合物,正好包含K种元素,那么将它们装车的时候,已经拿到的化合物再来的时候就应该拒绝装车,安全起见,然后给你装车的化合物列表,问你需要拒绝装车的次数. 解题思路:并查集.将已经装过的化合物记录下来,那么如果下次的化合物如果已经在集合中了,就说明需要拒绝装车. 代码: #include <cstdio> #include <cstring> const int maxn = 1e5 + 5; i

UVALive - 3027Corporative Network(带权并查集)

题目: UVALive - 3027Corporative Network(带权并查集) 题目大意:有n和节点,初始时每个节点的父节点都不存在,然后有下面两种操作:I 操作 I a,b 将a的父节点变成b.E操作 E a,查询a到它的父节点的距离. 解题思路:带权并查集.注意这里距离的变化是a -> b,那么a到根节点的距离就是a到b的距离的绝对值 % 1000 + b到它的根节点的距离. 代码: #include <cstdio> #include <cstring> #i

UVALive - 3027 - Corporative Network (并查集!!)

UVALive - 3027 Corporative Network Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description A very big corporation is developing its corporative network. In the beginning each of the N enterprises of the cor

UVALive 6910 Cutting Tree(并查集应用)

总体来说,这个题给的时间比较长,样例也是比较弱的,别的方法也能做出来. 我第一次使用的是不合并路径的并查集,几乎是一种暴力,花了600多MS,感觉还是不太好的,发现AC的人很多都在300MS之内的过得. 看到他们的做法后,我知道了这个题比较好的做法. 逆向思维的并查集,因为这里只有去边操作,完全可以离线计算,把删边当成加边,然后逆序输出答案即可. 但是,这个却有一个坑,很坑,只有第一次删除的时候,我们才对他进行操作,加边的时候也只能在第一次删除的时候加.当时因为这里,十分困惑-- 这是我无路径压