扫雷


题目描述:

小明最近迷上了一款名为《扫雷》的游戏。

其中有一个关卡的任务如下:

在一个二维平面上放置着 n 个炸雷,第 i 个炸雷 (x\(_i\),y\(_i\),r\(_i\)) 表示在坐标 (x\(_i\),y\(_i\)) 处存在一个炸雷,它的爆炸范围是以半径为 r\(_i\) 的一个圆。

为了顺利通过这片土地,需要玩家进行排雷。

玩家可以发射 m 个排雷火箭,小明已经规划好了每个排雷火箭的发射方向,第 j 个排雷火箭 (x\(_j\),y\(_j\),r\(_j\)) 表示这个排雷火箭将会在 (x\(_j\),y\(_j\)) 处爆炸,它的爆炸范围是以半径为 r\(_j\) 的一个圆,在其爆炸范围内的炸雷会被引爆。

同时,当炸雷被引爆时,在其爆炸范围内的炸雷也会被引爆。

现在小明想知道他这次共引爆了几颗炸雷?

你可以把炸雷和排雷火箭都视为平面上的一个点。

一个点处可以存在多个炸雷和排雷火箭。

当炸雷位于爆炸范围的边界上时也会被引爆。

解题思路:

  1. 暴力扫描所有可能爆炸的点:

    无疑啊,这种暴力的复杂度在O(n\(^2\))的,0<=n<=5e4,肯定会TLE滴

考虑到半径0<=r<=10,所以我们考虑能不能只扫描炸弹半径内可能会被引爆的点,那复杂度就会被降下来

  1. 哈希+bfs:

    我们将所有的炸弹用哈希映射到到一个唯一的哈希值然后在bfs的过程中,扫描当前炸弹的半径中是否存在炸弹(哈希查找),这样的总复杂度就在O(2r\(^2\)n+2r\(^2\)m)

    其中:bfs(O(n)),哈希(O(1))

哈希:map<key,val>

考虑哈希的细节:

  1. 二维坐标x,y唯一映射的哈希值:

    由于x,y的范围为[0,1e9],所以我们可以将x,y唯一的映射到一个哈希值(x*mod+y),mod = 1e9+1

    这就是将x,y映射为一个1e9+1进制的数,假设这个哈希值为h,那x = h/mod,y = h%mod
  2. 哈希表的长度:已知题目n小于等于5e4,哈希表的长度至少是2n,尽可能的开大空间,避免冲突的发生,同时哈希表的长度应该为一个质数,所以取1e6+7
  3. 哈希表的key:获取哈希值之后需要将其存入哈希表的一个位置,这个位置就是该哈希值的key。对长度取模即可,若冲突则后移。

代码实现:

# include<bits/stdc++.h>
using namespace std;
# define int long long
const int N = 5e4+10,M = 1e6+7,mod = 1e9+7;
int h[M];//哈希表
int id[M];//对应哈希key的炸弹下标
bool vis[N];//是否被引爆过
struct node{
int x,y,r;
}a[N];
int n,m; /*
哈希:map<key,value>
*/
int get_hs(int x,int y)//获取哈希值
{
return (int)x*mod+y;
}
int find(int x,int y)//获取哈希的key
{
int hs = get_hs(x,y);
int key = (hs%M+M)%M; while(h[key] != -1&&h[key] != hs)//如果冲突就后移
{
key++;
if(key == M) key = 0;
}
return key;
} bool check(int x,int y,int r,int a,int b)//是否会被引爆
{
int d = (x-a)*(x-a)+(y-b)*(y-b);
return d<=r*r;
} void bfs(int pos){
queue<int> q;
q.push(pos);
vis[pos] = 1;
while(q.size()){
int t = q.front();
q.pop();
int x = a[t].x,y = a[t].y,r = a[t].r;
/*
扫描整个半径内是否存在会被引爆的炸弹
*/
for(int xx = max(x-r,0ll);xx<=min(x+r,(int)1e9);++xx){
for(int yy = max(y-r,0ll);yy<=min(y+r,(int)1e9);++yy){
int key = find(xx,yy);
if(id[key]&&!vis[id[key]]&&check(x,y,r,xx,yy)){
int pos = id[key];
vis[pos] = 1;
q.push(pos);
}
}
}
}
} signed main(){
cin>>n>>m;
memset(h,-1,sizeof h);
int x,y,r;
for(int i = 1;i <= n;++i){
cin>>x>>y>>r;
a[i] ={x,y,r};
int key = find(x,y);//获取key
if(h[key] == -1) h[key] = get_hs(x,y);//存储哈希值 if(!id[key]||a[id[key]].r<r)//如果该点有炸弹,或者有一个半径更大的炸弹
{
id[key] = i;
}
} for(int i = 1;i <= m;++i){
cin>>x>>y>>r; // 扫描整个半径内是否存在会被引爆的炸弹 for(int xx = max(x-r,0ll);xx<=min(x+r,(int)1e9);++xx){
for(int yy = max(y-r,0ll);yy<=min(y+r,(int)1e9);++yy){
int key = find(xx,yy);
//是否有炸弹,是否被引爆过,是否能被引爆
if(id[key]&&!vis[id[key]]&&check(x,y,r,xx,yy)){
bfs(id[key]);
}
}
}
}
int ans = 0;
//扫描答案
for(int i = 1;i <= n;++i){
int key = find(a[i].x,a[i].y);
int pos = id[key];
if(pos&&vis[pos]) ans++;
}
cout<<ans<<endl; return 0;
}

扫雷(哈希+bfs)的更多相关文章

  1. 哈希+Bfs【P2730】 魔板 Magic Squares

    没看过题的童鞋请去看一下题-->P2730 魔板 Magic Squares 不了解康托展开的请来这里-->我这里 至于这题为什么可以用康托展开?(瞎说时间到. 因为只有8个数字,且只有1 ...

  2. 山东省第四届ACM省赛

    排名:http://acm.sdut.edu.cn/sd2012/2013.htm 解题报告:http://www.tuicool.com/articles/FnEZJb A.Rescue The P ...

  3. poj 2432 Around the world bfs+哈希

    由于每个点的状态包含走过来的距离,所以要存二维的状态,但是状态总量太多,所以可以用哈希来搞. 那么就是bfs最短路,哈希记录状态了. #include <iostream> #includ ...

  4. Eight(bfs+全排列的哈希函数)

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22207   Accepted: 9846   Special Judge ...

  5. UVA 10651 Pebble Solitaire(bfs + 哈希判重(记忆化搜索?))

    Problem A Pebble Solitaire Input: standard input Output: standard output Time Limit: 1 second Pebble ...

  6. hdu1067-Gap(bfs+哈希)

    Let's play a card game called Gap. You have 28 cards labeled with two-digit numbers. The first digit ...

  7. Poj2946-The Warehouse(bfs+哈希)

    题目我就不粘贴了... 题意:给出地图,最大8*8,出口用'E'表示,空地用'.'表示,数字表示此处有多少个箱子,主人公的起点应该是在有箱子的地方,他可以朝四个方向移动,但是只有两种方式 一种是他移动 ...

  8. 【算法】BFS+哈希解决八数码问题

    15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...

  9. POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)

    Description Let's play a puzzle using eight cubes placed on a 3 × 3 board leaving one empty square. ...

随机推荐

  1. K8s小白?应用部署太难?看这篇就够了!

    在云原生趋势下,容器和 Kubernetes 可谓是家喻户晓,许多企业内部的研发团队都在使用 Kubernetes 打造 DevOps 平台.从最早的容器概念到 Kubernetes 再到 DevOp ...

  2. 给ShardingSphere提了个PR,不知道是不是嫌弃我

    说来惭愧,干了 10 来年程序员,还没有给开源做过任何贡献,以前只知道嘎嘎写,出了问题嘎嘎改,从来没想过提个 PR 去修复他,最近碰到个问题,发现挺简单的,就随手提了个 PR 过去. 问题 问题挺简单 ...

  3. 域名+端口号 访问minio服务问题

    业务上需要用到分布式文件服务,选择了minio作为文件服务的组件,搭建好服务后使用IP+端口号(http://xx.xx.xx.xx:9001)的形式访问在所有环境下都没有问题. 上线部署时出于正规和 ...

  4. vue中处理过内存泄露处理方法

    1>意外的全局变量函数中意外的定义了全局变量,每次执行该函数都会生成该变量,且不会随着函数执行结束而释放. 2>未清除的定时器定时器没有清除,它内部引用的变量,不会被释放. 3>脱离 ...

  5. Macos下用pycharm运行django项目死活安装不上mysqlclient怎么办!!??

    花了我三天时间,佛了 我刚从win过渡到mac,想着把代码迁移一下. 然后看到依赖里面有一个mysqlclient,然后pip3 install死活装不上 解决方案: 在这里写上这个 然后就好,死了

  6. centos7换清华源

    一 删除其他源 cd /etc/yum.repos.d/ 二 创建源 vim CentOS-Base.repo # CentOS-Base.repo # # The mirror system use ...

  7. 用trie树解决最大异或对问题(On)

    在给定的N个整数A1,A2--ANA1,A2--AN中选出两个进行xor(异或)运算,得到的结果最大是多少? 输入格式 第一行输入一个整数N. 第二行输入N个整数A1A1-ANAN. 输出格式 输出一 ...

  8. 当web项目没有配置<welcome-file>index_1.jsp</welcome-file>默认标签启动tomcat后默认访问的页面是什么呢?

    当web项目没有配置index_1.jsp默认标签启动tomcat后默认访问的页面是什么呢? 结果我启动后居然默认打开了index.jsp页面 为什么呢?为什么会访问我的.indexjsp页面呢?不是 ...

  9. JAVA中方法的调用主要有以下几种

    JAVA中方法的调用主要有以下几种: 1.非静态方法 非静态方法就是没有 static 修饰的方法,对于非静态方法的调用,是通过对 象来调用的,表现形式如下. 对象名.方法() eg: public ...

  10. WSUS下载速度和BITS服务

    近日,新装了一台WSUS服务器.选择好需要同步的补丁类型和语言版本后开始等待同步.通过过程异常缓慢,速度一直上不去.同步了一整天才30G,同步3T数据需要100天.这样肯定没办法用,所以要想办法提高下 ...