蓝桥杯 - 试题 H: 扫雷(思维)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯 - 试题 H: 扫雷(思维)相关的知识,希望对你有一定的参考价值。


题目大意:给出 n n n 个地雷和 m m m 个炸弹,都以 ( x , y , r ) (x,y,r) (x,y,r) 的形式给出,意义分别如下:

  1. 对于每个地雷,位于点 ( x , y ) (x,y) (x,y),爆炸后会波及半径为 r r r 的圆形区域
  2. 对于每个炸弹,会在点 ( x , y ) (x,y) (x,y) 爆炸,爆炸后会引爆半径为 r r r 的圆形区域内的地雷,随后地雷会 “连锁反应” 的爆炸

问使用过 m m m 个炸弹后,一共可以引爆多少个地雷

题目分析:(赛时读错题了,怪不得当时算复杂度的时候能多算一个 l o g log log 出来)

最初的思想肯定是,先让可以“连锁反应”的地雷建立关系,这样引爆其中的一个地雷后,由“连锁反应”所引爆的地雷就不会被重复判断了,可以做到每个地雷至多被遍历一次。

需要发现一个很重要的细节就是,地雷引爆的关系是单向的,如果地雷 A 可以引爆地雷 B ,不一定能得出地雷 B 可以引爆地雷 A

所以整个“连锁反应”是一个有向图,不能使用并查集处理连通性。在建出有向图后索性直接用 dfs 暴力遍历即可,因为上面的思路已经保证了每个地雷至多遍历一次,所以 dfs 的复杂度是线性的

现在的问题转换为该如何快速建边,观察数据范围不难发现半径 r r r 给的特别小,所以可以将圆心用 map 映射一下,然后每次只需要遍历圆内的点尝试建边就好了

时间复杂度: O ( n ∗ 320 ∗ l o g n ) O(n*320*logn) O(n320logn),这里的 320 320 320 代表的是半径为 10 10 10 的圆内的点数

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e4+100;
struct Point 
	int x,y,r;
	void input() 
		scanf("%d%d%d",&x,&y,&r);
	
p1[N],p2[N];
bool vis[N];
map<pair<int,int>,vector<int>>mp;
vector<int>node[N];
int dfs(int u) 
	if(vis[u]) 
		return 0;
	
	vis[u]=true;
	int ans=1;
	for(auto v:node[u]) 
		ans+=dfs(v);
	
	return ans;

int main() 
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++) 
		p1[i].input();
		mp[p1[i].x,p1[i].y].push_back(i);
	
	for(int i=1;i<=m;i++) 
		p2[i].input();
	
	for(int i=1;i<=n;i++) 
		for(int dx=-10;dx<=10;dx++) 
			for(int dy=-10;dy<=10;dy++) 
				LL x=p1[i].x,y=p1[i].y;
				LL xx=x+dx,yy=y+dy;
				LL r=p1[i].r;
				if((x-xx)*(x-xx)+(y-yy)*(y-yy)<=r*r) 
					for(auto j:mp[xx,yy]) 
						node[i].push_back(j);
					
				
			
		
	
	int ans=0;
	for(int i=1;i<=m;i++) 
		for(int dx=-10;dx<=10;dx++) 
			for(int dy=-10;dy<=10;dy++) 
				LL x=p2[i].x,y=p2[i].y;
				LL xx=x+dx,yy=y+dy;
				LL r=p2[i].r;
				if((x-xx)*(x-xx)+(y-yy)*(y-yy)<=r*r) 
					for(auto j:mp[xx,yy]) 
						ans+=dfs(j);
					
				
			
		
	
	cout<<ans<<endl;
	return 0;

以上是关于蓝桥杯 - 试题 H: 扫雷(思维)的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯 - 试题 H: 扫雷(思维)

大战蓝桥杯每日算法详解解析(C/C++)

扫雷真题dfs(2022蓝桥杯)

第十三届蓝桥杯大赛软件赛省赛(C/C++ 大学B组)

蓝桥杯3月刷题集训-A 枚举&模拟Day3

蓝桥杯 - 试题 J: 砍竹子(双向链表+堆/思维)