扫雷
知识点
2024-12-3 蓝桥杯每日一题 扫雷 dfs (bfs也是可行的)
题目大意
在一个二维平面上放置这N个炸雷,每个炸雷的信息有$(x_i,y_i,r_i) $,前两个是坐标信息,第三个是爆炸半径。然后会输入M个排雷火箭,同样的信息;排雷火箭会将范围内所有的炸雷炸掉,并且会引发一连串爆炸这就要根据爆炸半径来判断。
解题思路
- 要考虑怎么存储这个炸弹信息,并且还要方便遍历到。在题目中坐标范围是 1 0 9 10^9 109,肯定不能存到二维数组的平面坐标中。
- 使用 m a p < p a i r < i n t , i n t > , v e c t o r < i n t > > map<pair<int,int>,vector<int>> map<pair<int,int>,vector<int>>,这样方便以O(1)的时间访问到当前位置,并且题目中明确表示同一个点可能会包含多个炸雷或火箭,(这一点一定看清楚),我就是这一点磕了一下;然后就是一定要使用map来定义,unordered_map我用的不行,应为这里使用到了pair。
- 最后就是递归遍历了,没输入一个火箭调用dfs;而且注意到 r 的的范围是很小的,我们就可以通过遍历当前位置为中心向四周扩展 r 长度的正方形,然后找到雷之后还要判断两点之间的距离是否在园内即可。
Accepted
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4+10;
typedef long long ll;
typedef pair<int,int> pii;
int n,m,cnt;
map<pii,vector<int>> a;
// 两点之间的距离
ll dist(int x1,int y1,int x2,int y2) {
return 1ll*(x1-x2)*(x1-x2) + 1ll*(y1-y2)*(y1-y2);
}
void dfs(int x,int y,int r) {
for(int i = x-r;i <= x+r;i++) {
for(int j = y-r;j <= y+r;j++) {
if(a.count({i,j})) {
int len = a[{i,j}].size();
for(int k = 0;k < len;k++) {
int rr = a[{i,j}][k];
if(rr > 0 && dist(i,j,x,y) <= 1ll*r*r) {
a[{i,j}][k] = 0;
cnt++;
dfs(i,j,rr);
}
}
}
}
}
}
int main()
{
int x,y,r;
cin>>n>>m;
for(int i = 1;i <= n;i++) {
cin>>x>>y>>r;
a[{x,y}].push_back(r);
}
while(m--) {
cin>>x>>y>>r;
dfs(x,y,r);
}
cout<<cnt;
return 0;
}
备注
欢迎大家一起来备战蓝桥杯。可以私信我加联系方式,人多的话咱就拉个群了。