2022第十三届蓝桥杯B组C++省赛H题 扫雷

【问题描述】

小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下, 在一个二维平面上放置着 n 个炸雷,第 i 个炸雷 (xi, yi, ri) 表示在坐标 (xi, yi) 处 存在一个炸雷,它的爆炸范围是以半径为 ri 的一个圆。 为了顺利通过这片土地,需要玩家进行排雷。玩家可以发射 m 个排雷火 箭,小明已经规划好了每个排雷火箭的发射方向,第 j 个排雷火箭 (xj, yj, rj) 表 示这个排雷火箭将会在 (xj, yj) 处爆炸,它的爆炸范围是以半径为 rj 的一个圆, 在其爆炸范围内的炸雷会被引爆。同时,当炸雷被引爆时,在其爆炸范围内的 炸雷也会被引爆。现在小明想知道他这次共引爆了几颗炸雷? 你可以把炸雷和排雷火箭都视为平面上的一个点。一个点处可以存在多个 炸雷和排雷火箭。当炸雷位于爆炸范围的边界上时也会被引爆。

【输入格式】

输入的第一行包含两个整数 n、m 接下来的 n 行,每行三个整数 xi , yi ,ri,表示一个炸雷的信息。 再接下来的 m 行,每行三个整数 xj , yj ,rj,表示一个排雷火箭的信息。

【输出格式】

输出一个整数表示答案。

【样例输入】

2 1

2 2 4

4 4 2

0 0 5

【样例输出】

2

【样例说明】

示例图如下,排雷火箭 1 覆盖了炸雷 1,所以炸雷 1 被排除;炸雷 1 又覆 盖了炸雷 2,所以炸雷 2 也被排除。

 

【评测用例规模与约定】

对于 40% 的评测用例:0 ≤ x, y ≤ 109 , 0 ≤ n, m ≤ 103 , 1 ≤ r ≤ 10.

对于 100% 的评测用例:0 ≤ x, y ≤ 109 , 0 ≤ n, m ≤ 5 × 104 , 1 ≤ r ≤ 10.


 

当时用dfs做的,最后一分钟还在挣扎在找错误TuT....

昨天看到的:“直接两重循环建边+dfs搜索的,会炸(因为建边是两重循环,过不叫第二个5e4的样例)”


 

一个只过了40%的代码(...)

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=50100;
 4 //炸雷的坐标和半径
 5 int x_pos[maxn];
 6 int y_pos[maxn];
 7 int radius[maxn];
 8 bool vis[maxn];//标记是否爆炸
 9 
10 struct point
11 {
12     int x,y,r;
13     //将结构体放入 map 中作为键,需要自己写一个 operator 来排序
14     bool operator<(const point &p)const
15     {
16         if(x==p.x)
17         {
18             if(y==p.y)
19                 {return r<p.r;}
20             return y<p.y;
21         }
22         return x<p.x;
23     }
24 };
25 
26 map<point,int>all;
27 
28 double getdis(int x1,int y1,int x2,int y2)
29 {
30     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
31 }
32 
33 int bfs(point begin,int n)
34 {
35     long long int cnt=0;
36     queue<point>q;
37     q.push(begin);
38     while(!q.empty())
39     {
40         point cur=q.front();
41         q.pop();
42         //遍历排雷火箭所在的最小正方形,找到其涉及爆炸的雷
43         for(register int i=cur.x-cur.r;i<=cur.x+cur.r;i++)
44         {
45             for(register int j=cur.y-cur.r;j<=cur.y+cur.r;j++)
46             {
47                 if(getdis(i,j,cur.x,cur.y)>cur.r)
48                     continue;
49                 point temp;
50                 temp.x=i;
51                 temp.y=j;
52                 for(register int k=0;k<n;k++)
53                 {
54                     if(!vis[k]&&x_pos[k]==temp.x&&y_pos[k]==temp.y)
55                     {
56                         temp.r=radius[k];
57                         q.push(temp);
58                         cnt++;
59                         vis[k]=true;//标记已炸
60                         all[temp]--;
61                     }
62                 }
63             }
64         }
65     }
66     return cnt;
67 }
68 
69 int main()
70 {
71     int n,m,cnt=0;
72     cin>>n>>m;
73     for(register int i=0;i<n;i++)
74     {
75         cin>>x_pos[i]>>y_pos[i]>>radius[i];
76         vis[i]=false;//初始化全部未炸
77     }
78     for(register int i=0;i<m;i++)
79     {
80         point p;
81         cin>>p.x>>p.y>>p.r;
82         cnt+=bfs(p,n);
83     }
84     cout<<cnt;
85     return 0;
86 }
复制代码

 

posted @   爱吃虾滑  阅读(410)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示