扫雷(哈希+bfs)
扫雷
题目描述:
小明最近迷上了一款名为《扫雷》的游戏。
其中有一个关卡的任务如下:
在一个二维平面上放置着 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\) 的一个圆,在其爆炸范围内的炸雷会被引爆。
同时,当炸雷被引爆时,在其爆炸范围内的炸雷也会被引爆。
现在小明想知道他这次共引爆了几颗炸雷?
你可以把炸雷和排雷火箭都视为平面上的一个点。
一个点处可以存在多个炸雷和排雷火箭。
当炸雷位于爆炸范围的边界上时也会被引爆。
解题思路:
- 暴力扫描所有可能爆炸的点:
无疑啊,这种暴力的复杂度在O(n\(^2\))的,0<=n<=5e4,肯定会TLE滴
考虑到半径0<=r<=10,所以我们考虑能不能只扫描炸弹半径内可能会被引爆的点,那复杂度就会被降下来
- 哈希+bfs:
我们将所有的炸弹用哈希映射到到一个唯一的哈希值然后在bfs的过程中,扫描当前炸弹的半径中是否存在炸弹(哈希查找),这样的总复杂度就在O(2r\(^2\)n+2r\(^2\)m)
其中:bfs(O(n)),哈希(O(1))
哈希:map<key,val>
考虑哈希的细节:
- 二维坐标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 - 哈希表的长度:已知题目n小于等于5e4,哈希表的长度至少是2n,尽可能的开大空间,避免冲突的发生,同时哈希表的长度应该为一个质数,所以取1e6+7
- 哈希表的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)的更多相关文章
- 哈希+Bfs【P2730】 魔板 Magic Squares
没看过题的童鞋请去看一下题-->P2730 魔板 Magic Squares 不了解康托展开的请来这里-->我这里 至于这题为什么可以用康托展开?(瞎说时间到. 因为只有8个数字,且只有1 ...
- 山东省第四届ACM省赛
排名:http://acm.sdut.edu.cn/sd2012/2013.htm 解题报告:http://www.tuicool.com/articles/FnEZJb A.Rescue The P ...
- poj 2432 Around the world bfs+哈希
由于每个点的状态包含走过来的距离,所以要存二维的状态,但是状态总量太多,所以可以用哈希来搞. 那么就是bfs最短路,哈希记录状态了. #include <iostream> #includ ...
- Eight(bfs+全排列的哈希函数)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22207 Accepted: 9846 Special Judge ...
- UVA 10651 Pebble Solitaire(bfs + 哈希判重(记忆化搜索?))
Problem A Pebble Solitaire Input: standard input Output: standard output Time Limit: 1 second Pebble ...
- hdu1067-Gap(bfs+哈希)
Let's play a card game called Gap. You have 28 cards labeled with two-digit numbers. The first digit ...
- Poj2946-The Warehouse(bfs+哈希)
题目我就不粘贴了... 题意:给出地图,最大8*8,出口用'E'表示,空地用'.'表示,数字表示此处有多少个箱子,主人公的起点应该是在有箱子的地方,他可以朝四个方向移动,但是只有两种方式 一种是他移动 ...
- 【算法】BFS+哈希解决八数码问题
15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...
- 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. ...
随机推荐
- K8s小白?应用部署太难?看这篇就够了!
在云原生趋势下,容器和 Kubernetes 可谓是家喻户晓,许多企业内部的研发团队都在使用 Kubernetes 打造 DevOps 平台.从最早的容器概念到 Kubernetes 再到 DevOp ...
- 给ShardingSphere提了个PR,不知道是不是嫌弃我
说来惭愧,干了 10 来年程序员,还没有给开源做过任何贡献,以前只知道嘎嘎写,出了问题嘎嘎改,从来没想过提个 PR 去修复他,最近碰到个问题,发现挺简单的,就随手提了个 PR 过去. 问题 问题挺简单 ...
- 域名+端口号 访问minio服务问题
业务上需要用到分布式文件服务,选择了minio作为文件服务的组件,搭建好服务后使用IP+端口号(http://xx.xx.xx.xx:9001)的形式访问在所有环境下都没有问题. 上线部署时出于正规和 ...
- vue中处理过内存泄露处理方法
1>意外的全局变量函数中意外的定义了全局变量,每次执行该函数都会生成该变量,且不会随着函数执行结束而释放. 2>未清除的定时器定时器没有清除,它内部引用的变量,不会被释放. 3>脱离 ...
- Macos下用pycharm运行django项目死活安装不上mysqlclient怎么办!!??
花了我三天时间,佛了 我刚从win过渡到mac,想着把代码迁移一下. 然后看到依赖里面有一个mysqlclient,然后pip3 install死活装不上 解决方案: 在这里写上这个 然后就好,死了
- centos7换清华源
一 删除其他源 cd /etc/yum.repos.d/ 二 创建源 vim CentOS-Base.repo # CentOS-Base.repo # # The mirror system use ...
- 用trie树解决最大异或对问题(On)
在给定的N个整数A1,A2--ANA1,A2--AN中选出两个进行xor(异或)运算,得到的结果最大是多少? 输入格式 第一行输入一个整数N. 第二行输入N个整数A1A1-ANAN. 输出格式 输出一 ...
- 当web项目没有配置<welcome-file>index_1.jsp</welcome-file>默认标签启动tomcat后默认访问的页面是什么呢?
当web项目没有配置index_1.jsp默认标签启动tomcat后默认访问的页面是什么呢? 结果我启动后居然默认打开了index.jsp页面 为什么呢?为什么会访问我的.indexjsp页面呢?不是 ...
- JAVA中方法的调用主要有以下几种
JAVA中方法的调用主要有以下几种: 1.非静态方法 非静态方法就是没有 static 修饰的方法,对于非静态方法的调用,是通过对 象来调用的,表现形式如下. 对象名.方法() eg: public ...
- WSUS下载速度和BITS服务
近日,新装了一台WSUS服务器.选择好需要同步的补丁类型和语言版本后开始等待同步.通过过程异常缓慢,速度一直上不去.同步了一整天才30G,同步3T数据需要100天.这样肯定没办法用,所以要想办法提高下 ...