题目描述
兰博An为了拯救宇宙,来到一块雷区。假设雷区为一个水平的二维平面,雷区中被放置了 n个地雷。假设地雷自身占据的面积忽略不计,从而看成是平面中的一个点,其中第 i 个地雷的坐标为 (xi , yi) ,其爆炸范围为一个半径为 ri 的圆。
兰博An为了闯过雷区继续完成任务,向雷区扔了共计m 颗手雷,第 j 个手雷的坐标为(xj , yj ),其爆炸范围为一个半径为 rj 的圆,同时手雷会引爆其爆炸范围内的地雷,而当一颗地雷被引爆时,在其爆炸范围内的其它地雷也会同时引爆,产生连环引爆。问:兰博An在这次排雷行动中共引爆了几颗地雷?
注意:平面中可能存在一个点内有多个地雷和手雷。位于爆炸边界上的地雷一样会被引爆。
【提示】
示例图如下,手雷 1 覆盖了地雷 1,所以地雷 1 被排除;地雷 1 又覆盖了地雷 2,所以地雷 2 也被排除。
![](https://img-blog.csdnimg.cn/img_convert/779074b8c7944152a2d897573dccedfd.png)
0 ≤ x, y ≤ 10^9 , 0 ≤ n, m ≤ 10^3 , 1 ≤ r ≤ 10.
输入格式
输入文件名:mine.in
输入的第一行包含两个整数 n、m.
接下来的 n 行,每行三个整数 xi , yi ,ri,表示一个地雷的信息。
再接下来的 m 行,每行三个整数 xj , yj ,rj,表示一个手雷的信息。
输出格式
输出文件名:mine.out
输出一个整数表示答案。
输入/输出例子1
输入:
2 1
2 2 4
4 4 2
0 0 5
输出:
2
其实不难:
#include<bits/stdc++.h>
using namespace std;
const int maxn=50100;
int x_pos[maxn];
int y_pos[maxn];
int radius[maxn];
bool vis[maxn];
struct point
{
int x,y,r;
bool operator<(const point &p)const
{
if(x==p.x)
{
if(y==p.y)
{return r<p.r;}
return y<p.y;
}
return x<p.x;
}
};
map<point,int>all;
double getdis(int x1,int y1,int x2,int y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int bfs(point begin,int n)
{
long long int cnt=0;
queue<point>q;
q.push(begin);
while(!q.empty())
{
point cur=q.front();
q.pop();
for(register int i=cur.x-cur.r;i<=cur.x+cur.r;i++)
{
for(register int j=cur.y-cur.r;j<=cur.y+cur.r;j++)
{
if(getdis(i,j,cur.x,cur.y)>cur.r)
continue;
point temp;
temp.x=i;
temp.y=j;
for(register int k=0;k<n;k++)
{
if(!vis[k]&&x_pos[k]==temp.x&&y_pos[k]==temp.y)
{
temp.r=radius[k];
q.push(temp);
cnt++;
vis[k]=true;
all[temp]--;
}
}
}
}
}
return cnt;
}
int main()
{
freopen("mine.in","r",stdin);
freopen("mine.out","w",stdout);
int n,m,cnt=0;
cin>>n>>m;
for(register int i=0;i<n;i++)
{
cin>>x_pos[i]>>y_pos[i]>>radius[i];
vis[i]=false;
}
for(register int i=0;i<m;i++)
{
point p;
cin>>p.x>>p.y>>p.r;
cnt+=bfs(p,n);
}
cout<<cnt;
return 0;
}