草庐IT

蓝桥杯2022初赛——扫雷

疯疯癫癫才自由 2023-04-19 原文

4407. 扫雷

小明最近迷上了一款名为《扫雷》的游戏。

其中有一个关卡的任务如下:

在一个二维平面上放置着 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

,表示一个排雷火箭的信息。

输出格式

输出一个整数表示答案。

数据范围

对于 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

输入样例:

2 1
2 2 4
4 4 2
0 0 5

输出样例:

2

样例解释

示例图如下,排雷火箭 1

覆盖了炸雷 1,所以炸雷 1 被排除;炸雷 1 又覆盖了炸雷 2,所以炸雷 2

也被排除。

排雷火箭可以排掉地雷,地雷又可以排掉它能排掉范围内的地雷,所以显然是图的遍历问题。

可是,如果不对原始数据进行处理,直接用邻接表或者临界矩阵来建图,明显会超时。因为点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9。但是先把坐标按x轴从小到大排序,再按y轴从小到大排序,时间复杂度是O(nlgn),再加上建图的时间复杂度O(n*r),查询的时间复杂度O(m*lgn+n)。可以AC。

这道题我花了数日,研究了数种方法,有map解决,unordered_map解决,有手写hash表解决,能AC的BFS和DFS我都写出来了,不是y总讲的方法,便是在acwing上看到大佬写的代码,自己动手写了一遍。不言而喻,效率比较:手写hash > unordered_map > map,

不过话说回来,在这道题中让我学到的知识蛮不少的。

代码中我有一些调试的代码,我没删除,那一部分到也没必要看,我都注释掉了的。

一共十一种代码,能AC的倒没几种,不过在写的过程中,是满满的收获啊。学到了如何手写hash表,map和unorded_map的效率差别,知道了当自己写的结构体或者pair作为unordered_map的key值的时候,需要自己写一个函数来对他们排序,因为编译器无法知道他们的关系。当然这个函数要用类来封装。想必以后也能用上lower_bound()和upper_bound了吧。虽然都知道这些函数,但是不知道什么时候用,还是自己写的题目太少了。同志,革命尚未成功,吾得急需努力。

其实算法笔记讲解BFS的时候就已经强调了inq表示结点是否入队,而不是是否访问,否则就会存在多个点进行入队,这和DFS的vis数组是有区别的,当时还不以为然,觉得自己都理解了,现在想想,亦是惭愧!书你倒是看了,但你是否真正的吸收了呢?每学到一个算法,就要去找相应的题目来做,不然你也只是白白浪费时间,多了不说,算法笔记上的树状数组以及lowbit数组你现在是否还能知道它们的意思,KMP算法是否还有印象,快速排序是否还能写出来,组合数的知识还知道多少。。。等等,不光是低头做题,还得总结自己学到的东西,以后遇到能够用自己学过的算法解决的题目的时候,别两眼一蹬,我不会,毫无思路?那就从此处开始,把之前写的算法发成博客吧,也能再温习一遍。

万丈高楼平地起,莫在浮沙筑高台!

第一种,图的深度优先遍历,邻接表实现,  由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,  明显会超时。

/**
    图的深度优先遍历,邻接表实现
    由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    明显会超时
*/
/**
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;

const int maxn=1010;
struct Node
{
    int x,y,r;
}cir[maxn];
vector<int> adj[maxn];
bool vis[maxn]={false};
int n,m;
int dfs_Trave(int x,int y,int r);
int dfs(int index);
void add(int index);
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        cir[i]={x,y,r};
    }

    for(int i=0;i<n;++i)
    {
        add(i);
    }
//    cout << "调试:\n";
//    for(int i=0;i<n;++i)
//    {
//        for(auto b:adj[i])
//            cout << b << ' ';
//        cout << endl;
//    }
//    cout << "jk\n";
    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
       // cout << "r:" << r << endl;
        //printf("r:%d\n",r);
        res+=dfs_Trave(x,y,r);
    }

    printf("%d\n",res);
    return 0;
}

void add(int index)
{
    for(int i=0;i<n;++i)
        if(i!=index)
        {
            if(cir[index].r>(sqrt(pow(cir[i].x-cir[index].x,2)+pow(cir[i].y-cir[index].y,2))))
                adj[index].push_back(i);
        }
}

int dfs(int index)
{
    //cout << "jinbulai?\n";
    int sum=1;
    vis[index]=true;
    for(int i=0;i<adj[index].size();++i)
    {
        int v=adj[index][i];
        if(vis[v]==false)
            sum+=dfs(v);
    }
    return sum;

}

int dfs_Trave(int x,int y,int r)
{
   // cout << "r:" << r << endl;
    int sum=0;
    for(int i=0;i<n;++i)
    {
        double L=sqrt(pow(x-cir[i].x,2)+pow(y-cir[i].y,2));
      //  cout << "length:" << L << endl;
        if(r>L)
        {
           // cout << "error: \n";
            if(vis[i]==false)
                sum+=dfs(i);
        }
    }
    return sum;
}

第二种, 图的深度优先遍历,邻接表实现,由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,先把坐标按x轴从小到大排序,再按y轴从小到大排序, acwing 最后一组数据通不过,最开始的时候始终找不出原因,现在想想,也能理解,
    当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    不然建图的时候有O(n^2)的时间复杂度。
    下一个代码我给出了AC的代码;
*/

/**
    图的深度优先遍历,邻接表实现
    由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    先把坐标按x轴从小到大排序,再按y轴从小到大排序
    acwing 最后一组数据通不过,最开始的时候始终找不出原因,现在想想,也能理解,
    当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    不然建图的时候有O(n^2)的时间复杂度。
    下一个代码我给出了AC的代码;
*/

/**
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <unordered_map>
using namespace std;

const int maxn=50010;
struct Node
{
    int x,y,r;
    int cnt;

    Node (int _x,int _y) : x(_x),y(_y){}
    Node (int _x,int _y,int _r) : x(_x),y(_y),r(_r){}
    Node (int _x,int _y,int _r,int _cnt) :x(_x),y(_y),r(_r),cnt(_cnt){}
    Node()=default;
    bool operator < (Node const & a) const
    {
        if(x!=a.x)
            return x<a.x;
        return y<a.y;
    }
}cir[maxn];
struct comp
{
    int operator()(const std::pair<int, int>& p) const {
        return p.first ^ p.second;  //返回值为bool,比较符为&,|都比这一个慢,
    }
};
typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}
vector<int> adj[maxn];
unordered_map<pair<int,int> ,int,comp> ump;
bool vis[maxn]={false};
int n,m;
int dfs_Trave(int x,int y,int r);
int dfs(int index);
void add(int index);
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        auto temp=ump[{x,y}];
        if(temp!=0)
        {
           cir[temp].r=max(cir[temp].r,r);
           cir[temp].cnt++;
        }
        else
        {
            cir[i]={x,y,r,1};   //应当用一个全局变量来表示不重复点的下标
            ump[{x,y}]=i;       //
        }
    }
    sort(cir+1,cir+n+1);

//    Node temp={2,3,9};
//    auto it=lower_bound(cir+1,cir+n+1,temp);
//    cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
//    Node temp2={2,50,9};
//    it=lower_bound(cir+1,cir+n+1,temp2);
//    cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
//    cout << "调试:\n";
//    for(int i=1;i<=n;++i)
//        cout << cir[i].x << ' ' << cir[i].y << ' ' << cir[i].r << endl;
//    cout << "ok\n";
    for(int i=1;i<=n;++i)
    {
        add(i);
    }
//    cout << "调试:\n";
//    for(int i=0;i<n;++i)
//    {
//        for(auto b:adj[i])
//            cout << b << ' ';
//        cout << endl;
//    }
//    cout << "jk\n";
    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
       // cout << "r:" << r << endl;
        //printf("r:%d\n",r);
        res+=dfs_Trave(x,y,r);
    }

    printf("%d\n",res);
    return 0;
}

void add(int index)
{
    for(int i=index-1;i>0;--i)
    {
        if(squ(cir[index].r)<squ(cir[i].x-cir[index].x))
            break;
        if(squ(cir[index].r)>=squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
            adj[index].push_back(i);
    }

    for(int i=index+1;i<=n;++i)
    {
        if(squ(cir[index].r) < squ(cir[i].x-cir[index].x))
           break;
        if(squ(cir[index].r) >= squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
            adj[index].push_back(i);
    }
}

int dfs(int index)
{
    int sum=cir[index].cnt;
    vis[index]=1;
    for(int i=0;i<adj[index].size();++i)
    {
        int v=adj[index][i];
        if(vis[v]==0)
            sum+=dfs(v);
    }
    return sum;

}

int dfs_Trave(int x,int y,int r)
{
    Node e1={x-r,y,r},e2={x+r,y,r};
    int l=lower_bound(cir+1,cir+n+1,e1)-cir;
    int ri=lower_bound(cir+1,cir+n+1,e2)-cir;
    l=min(l,n),ri=min(ri,n);
    int sum=0;
    for(int i=l;i<=ri;++i)
    {
        if(i==0)
            continue;
        if((squ(r)>=squ(cir[i].x-x)+squ(cir[i].y-y))&&vis[i]==0)
            sum+=dfs(i);
    }
    return sum;
}

第三个,/**
    图的深度优先遍历,邻接表实现
    由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    先把坐标按x轴从小到大排序,再按y轴从小到大排序
    当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    不然建图的时候有O(n^2)的时间复杂度。
    能AC

/**
    图的深度优先遍历,邻接表实现
    由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    先把坐标按x轴从小到大排序,再按y轴从小到大排序
    当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    不然建图的时候有O(n^2)的时间复杂度。
    能AC
*/

/**
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <unordered_map>
using namespace std;

const int maxn=50010;
struct Node
{
    int x,y,r;
    int cnt;

    Node (int _x,int _y) : x(_x),y(_y){}
    Node (int _x,int _y,int _r) : x(_x),y(_y),r(_r){}
    Node (int _x,int _y,int _r,int _cnt) :x(_x),y(_y),r(_r),cnt(_cnt){}
    Node()=default;
    bool operator < (Node const & a) const
    {
        if(x!=a.x)
            return x<a.x;
        return y<a.y;
    }
}cir[maxn];
struct comp
{
    int operator()(const std::pair<int, int>& p) const {
        return p.first ^ p.second;  //返回值为bool,比较符为&,|都比这一个慢,
    }
};
typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}
vector<int> adj[maxn];
unordered_map<pair<int,int> ,int,comp> ump; //实践上机证明将坐标转化为long long 比这种方式快上一点
bool vis[maxn]={false};
int n,m,n1=0;
int dfs_Trave(int x,int y,int r);
int dfs(int index);
void add(int index);
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        auto temp=ump[{x,y}];
        if(temp!=0)
        {
           cir[temp].r=max(cir[temp].r,r);
           cir[temp].cnt++;
        }
        else
        {
            cir[++n1]={x,y,r,1};
            ump[{x,y}]=n1;
           // cir[i].cnt=1;
        }
    }
    sort(cir+1,cir+n1+1);

//    Node temp={2,3,9};
//    auto it=lower_bound(cir+1,cir+n+1,temp);
//    cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
//    Node temp2={2,50,9};
//    it=lower_bound(cir+1,cir+n+1,temp2);
//    cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
//    cout << "调试:\n";
//    for(int i=1;i<=n;++i)
//        cout << cir[i].x << ' ' << cir[i].y << ' ' << cir[i].r << endl;
//    cout << "ok\n";
    for(int i=1;i<=n1;++i)
    {
        add(i);
    }
    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        res+=dfs_Trave(x,y,r);
    }

    printf("%d\n",res);
    return 0;
}

void add(int index)
{
    for(int i=index-1;i>0;--i)
    {
        if(squ(cir[index].r)<squ(cir[i].x-cir[index].x))
            break;
        if(squ(cir[index].r)>=squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
            adj[index].push_back(i);
    }

    for(int i=index+1;i<=n1;++i)
    {
        if(squ(cir[index].r) < squ(cir[i].x-cir[index].x))
           break;
        if(squ(cir[index].r) >= squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
            adj[index].push_back(i);
    }
}

int dfs(int index)
{
    int sum=cir[index].cnt;
    vis[index]=1;
    for(int i=0;i<adj[index].size();++i)
    {
        int v=adj[index][i];
        if(vis[v]==0)
            sum+=dfs(v);
    }
    return sum;

}

int dfs_Trave(int x,int y,int r)
{
    Node e1={x-r,y,r},e2={x+r,y,r};
    int l=lower_bound(cir+1,cir+n1+1,e1)-cir;
    int ri=lower_bound(cir+1,cir+n1+1,e2)-cir;
    l=min(l,n1),ri=min(ri,n1);
    int sum=0;
    for(int i=l;i<=ri;++i)
    {
        if(i==0)
            continue;
        if((squ(r)>=squ(cir[i].x-x)+squ(cir[i].y-y))&&vis[i]==0)
            sum+=dfs(i);
    }
    return sum;
}

第四个, 图的广度优先遍历,邻接表实现
    由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    先把坐标按x轴从小到大排序,再按y轴从小到大排序
    当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    不然建图的时候有O(n^2)的时间复杂度。
    能AC

/**
    图的广度优先遍历,邻接表实现
    由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    先把坐标按x轴从小到大排序,再按y轴从小到大排序
    当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    不然建图的时候有O(n^2)的时间复杂度。
    能AC
*/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;

const int maxn=50010;
struct Node
{
    int x,y,r;
    int cnt;

    Node (int _x,int _y) : x(_x),y(_y){}
    Node (int _x,int _y,int _r) : x(_x),y(_y),r(_r){}
    Node (int _x,int _y,int _r,int _cnt) :x(_x),y(_y),r(_r),cnt(_cnt){}
    Node()=default;
    bool operator < (Node const & a) const
    {
        if(x!=a.x)
            return x<a.x;
        return y<a.y;
    }
}cir[maxn];
struct comp
{
    int operator()(const std::pair<int, int>& p) const {
        return p.first ^ p.second;  //返回值为bool,比较符为&,|都比这一个慢,
    }
};
typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}
vector<int> adj[maxn];
unordered_map<pair<int,int> ,int,comp> ump; //实践上机证明将坐标转化为long long 比这种方式快上一点
bool vis[maxn]={false};
int n,m,n1=0;
int bfs_Trave(int x,int y,int r);
int bfs(int index);
void add(int index);
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        auto temp=ump[{x,y}];
        if(temp!=0)
        {
           cir[temp].r=max(cir[temp].r,r);
           cir[temp].cnt++;
        }
        else
        {
            cir[++n1]={x,y,r,1};
            ump[{x,y}]=n1;
           // cir[i].cnt=1;
        }
    }
    sort(cir+1,cir+n1+1);

//    Node temp={2,3,9};
//    auto it=lower_bound(cir+1,cir+n+1,temp);
//    cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
//    Node temp2={2,50,9};
//    it=lower_bound(cir+1,cir+n+1,temp2);
//    cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
//    cout << "调试:\n";
//    for(int i=1;i<=n;++i)
//        cout << cir[i].x << ' ' << cir[i].y << ' ' << cir[i].r << endl;
//    cout << "ok\n";
    for(int i=1;i<=n1;++i)
    {
        add(i);
    }
    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        res+=bfs_Trave(x,y,r);
    }

    printf("%d\n",res);
    return 0;
}

void add(int index)
{
    for(int i=index-1;i>0;--i)
    {
        if(squ(cir[index].r)<squ(cir[i].x-cir[index].x))
            break;
        if(squ(cir[index].r)>=squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
            adj[index].push_back(i);
    }

    for(int i=index+1;i<=n1;++i)
    {
        if(squ(cir[index].r) < squ(cir[i].x-cir[index].x))
           break;
        if(squ(cir[index].r) >= squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
            adj[index].push_back(i);
    }
}

int bfs(int index)
{
    queue<int> q;
    q.push(index);
    int sum=cir[index].cnt;
    while(!q.empty())
    {
        int top=q.front();
        q.pop();
        for(int i=0;i<adj[top].size();++i)
        {
            int v=adj[top][i];
            if(vis[v]==0)
            {
                vis[v]=1;
                sum+=cir[v].cnt;
                q.push(v);
            }
        }
    }

    return sum;

}

int bfs_Trave(int x,int y,int r)
{
    Node e1={x-r,y,r},e2={x+r,y,r};
    int l=lower_bound(cir+1,cir+n1+1,e1)-cir;
    int ri=lower_bound(cir+1,cir+n1+1,e2)-cir;
    l=min(l,n1),ri=min(ri,n1);
    int sum=0;
    for(int i=l;i<=ri;++i)
    {
        if(i==0)
            continue;
        if((squ(r)>=squ(cir[i].x-x)+squ(cir[i].y-y))&&vis[i]==0)
        {
            vis[i]=1;
            sum+=bfs(i);
        }
    }
    return sum;
}

第五个,/**
    map,将坐标用pair<int,int>存在map中
*/
/**
    1)每输入一个排雷火箭,就算出它排掉了多少雷,但是由于一个位置有多个雷
    ,所以要把这个位置的地雷数给记录下来;
    acwing通过5/11
*/

/**
    map,将坐标用pair<int,int>存在map中
*/
/**
    1)每输入一个排雷火箭,就算出它排掉了多少雷,但是由于一个位置有多个雷
    ,所以要把这个位置的地雷数给记录下来;
    acwing通过5/11
*/
/**
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
using namespace std;

typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}

map<pair<int,int>,pair<int,int> > mp;
map<pair<int,int>,int > vis;
int n,m;
int dfs_Trave(int x,int y,int r);
int dfs(pair<pair<int,int>,pair<int,int> > index);
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        auto temp=make_pair(x,y);
        auto it=mp.find(temp);
        if(it==mp.end())
        {
            vis[temp]=0;
            auto val=make_pair(r,1);
            mp[temp]=val;
        }
        else
        {
            if(r>it->second.first)
            {
                auto val=make_pair(r,it->second.second+1);
                mp[temp]=val;
            }
            else
            {
                auto val=make_pair(it->second.first,it->second.second+1);
                mp[temp]=val;
            }
        }

    }

    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        res+=dfs_Trave(x,y,r);
    }

    printf("%d\n",res);
    return 0;
}

int dfs(pair<pair<int,int>,pair<int,int> > index)
{
    int x=index.first.first,y=index.first.second,r=index.second.first,num=index.second.second;
    int sum=num;
    //cout << "调试:" << sum << endl;
    vis[index.first]=1;
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                auto temp=make_pair(l,s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        sum+=dfs(*it);
                }
            }
        }
    return sum;

}

int dfs_Trave(int x,int y,int r)
{
    int sum=0;
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                auto temp=make_pair(l,s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        sum+=dfs(*it);
                }
            }
        }
    return sum;
}
*/

第六个,/**
    2)先把排掉的雷给记录下来,最后统一计算,只记录半径,不用记录每个位置有多少雷;
    当相应的就需要把所有的地雷的位置给记录下来,即使他们是相同的位置这就是cir数组的作用
    acwing也是通过5/11
*/

/**
    2)先把排掉的雷给记录下来,最后统一计算,只记录半径,不用记录每个位置有多少雷;
    当相应的就需要把所有的地雷的位置给记录下来,即使他们是相同的位置这就是cir数组的作用
    acwing也是通过5/11
*/

/**
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
using namespace std;

typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}
const int maxn=50010;
struct Node
{
    int x,y,r;
}cir[maxn];
map<pair<int,int>,int > mp;
map<pair<int,int>,int > vis;
int n,m;
void dfs_Trave(int x,int y,int r);
void dfs(pair<pair<int,int>,int > index);
int main()
{
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        cir[i]={x,y,r};
        auto temp=make_pair(x,y);
        auto it=mp.find(temp);
        if(it==mp.end())
        {
            vis[temp]=0;
            mp[temp]=r;
        }
        else
        {
            if(r>it->second)
                mp[temp]=r;
        }
    }

    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        dfs_Trave(x,y,r);
    }

    for(int i=0;i<n;++i)
    {
        auto temp=make_pair(cir[i].x,cir[i].y);
        if(vis[temp]!=0)
            ++res;
    }
    printf("%d\n",res);
    return 0;
}

void dfs(pair<pair<int,int>,int > index)
{
    int x=index.first.first,y=index.first.second,r=index.second;
    vis[index.first]=1;
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                auto temp=make_pair(l,s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(*it);
                }
            }
        }

}

void dfs_Trave(int x,int y,int r)
{
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                auto temp=make_pair(l,s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(*it);
                }
            }
        }
}
*/

第七个,/**
    unorder_map解决,将坐标用pair<int,int>存在unordered_map中
*/
/**
    1)对于没有默认的哈希函数的类型,如自定义的 class 类型,pair 类型等,我们就必须自己
    指定一个哈希函数。这也是为什么直接构建 pair 类型的 unordered_set
    如 unordered_set<pair<int, int>> uset 会出现问题
    acwing通过5/11
*/

/**
    unorder_map解决,将坐标用pair<int,int>存在unordered_map中
*/
/**
    1)对于没有默认的哈希函数的类型,如自定义的 class 类型,pair 类型等,我们就必须自己
    指定一个哈希函数。这也是为什么直接构建 pair 类型的 unordered_set
    如 unordered_set<pair<int, int>> uset 会出现问题
    acwing通过5/11
*/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <unordered_map>
using namespace std;

typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}
const int maxn=50010;
/*
struct cmp
{
    bool operator()(pair<int,int> const &p) const
    {
        return p.first<p.second;
    }
};
*/
//struct cmp
//{
//    std::size_t operator()(const std::pair<int, int>& p) const {
//        return p.first ^ p.second;
//    }
//};

struct cmp
{
    int operator()(const std::pair<int, int>& p) const {
        return p.first ^ p.second;  //返回值为bool,比较符为&,|都比这一个慢,
    }
};
struct Node
{
    int x,y,r;
}cir[maxn];
unordered_map<pair<int,int>,int ,cmp> mp;
unordered_map<pair<int,int>,int ,cmp> vis;
int n,m;
void dfs_Trave(int x,int y,int r);
void dfs(pair<pair<int,int>,int > index);
int main()
{
//    int a=123456789,b=123456;
//    int c=a&b;
//    cout << c << endl;
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        cir[i]={x,y,r};
        auto temp=make_pair(x,y);
        auto it=mp.find(temp);
        if(it==mp.end())
        {
            vis[temp]=0;
            mp[temp]=r;
        }
        else
        {
            if(r>it->second)
                mp[temp]=r;
        }
    }
/*
    cout << "调试:\n";
    for(auto val:mp)
        cout << val.first.first << ' ' << val.first.second << ' ' << val.second << endl;
        */
    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        dfs_Trave(x,y,r);
    }

    for(int i=0;i<n;++i)
    {
        auto temp=make_pair(cir[i].x,cir[i].y);
        if(vis[temp]!=0)
            ++res;
    }
    printf("%d\n",res);
    return 0;
}

void dfs(pair<pair<int,int>,int > index)
{
    int x=index.first.first,y=index.first.second,r=index.second;
    vis[index.first]=1;
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                auto temp=make_pair(l,s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(*it);
                }
            }
        }

}

void dfs_Trave(int x,int y,int r)
{
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                auto temp=make_pair(l,s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(*it);
                }
            }
        }
}

第八个,/**
    将坐标转换为一个long long数值,存在unorder_map中;
    acwing通过了6/11;
*/

/**
    将坐标转换为一个long long数值,存在unorder_map中;
    acwing通过了6/11;
*/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;

typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}
const int maxn=50010,inf=1e9;

LL hash_val(int x,int y)
{
    return x*(inf+1ll)+y;
}
/*
struct cmp
{
    bool operator()(pair<int,int> const &p) const
    {
        return p.first<p.second;
    }
};
*/
//struct cmp
//{
//    std::size_t operator()(const std::pair<int, int>& p) const {
//        return p.first ^ p.second;
//    }
//};

//struct cmp
//{
//    int operator()(const LL, int>& p) const {
//        return p.first < p.second;
//    }
//};
//struct Node
//{
//    int x,y,r;
//}cir[maxn];
vector<LL> cir;
unordered_map<LL,int> mp;
unordered_map<LL,int> vis;
int n,m;
void dfs_Trave(int x,int y,int r);
void dfs(int x,int y,int r);
int main()
{

//    int a=123456789,b=123456;
//    int c=a&b;
//    cout << c << endl;

//    int a=123456789,b=45612;
//    cout << hash_val(a,b) << endl;

    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        //cir[i]={x,y,r};
        LL temp=hash_val(x,y);
        //string temp=to_string(val);
        cir.push_back(temp);
//        mp[temp]=r;
//        vis[temp]=0;
        auto it=mp.find(temp);
        if(it==mp.end())
        {
            vis[temp]=0;
            mp[temp]=r;
        }
        else
        {
            if(r>it->second)
                mp[temp]=r;
        }
    }

//    cout << "调试:\n";
//    for(auto val:mp)
//        cout << val.first << ' ' << val.second  << endl;
//    cout << "\ntiaoshi\n";
//    for(auto a:vis)
//        cout << a.first << ' ' << a.second << endl;
    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        dfs_Trave(x,y,r);
    }

//    cout << "\ntiaoshi2:\n";
//    for(auto a:vis)
//        cout << a.first << ' ' << a.second << endl;
    for(int i=0;i<n;++i)
    {
        auto temp=cir[i];
        if(vis[temp]!=0)
            ++res;
    }
    printf("%d\n",res);
    return 0;
}

void dfs(int x,int y,int r)
{
    LL val=hash_val(x,y);
   // int x=index.first.first,y=index.first.second,r=index.second;
    vis[val]=1;
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                auto temp=hash_val(l,s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(l,s,it->second);
                }
            }
        }

}

void dfs_Trave(int x,int y,int r)
{
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                LL temp=hash_val(l,s);
                //string temp=to_string(val);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(l,s,it->second);
                }
            }
        }
}

第九个,

/**
    将坐标转换为string,存在unordered_map中
    在acwing只能过4/11;

*/

/**
    将坐标转换为string,存在unordered_map中
    在acwing只能过4/11;

*/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;

typedef long long LL;
LL squ(int x)
{
    return (LL) x*x;
}
const int maxn=50010,inf=1e9;

LL hash_val(int x)
{
    return x*(inf+1ll);
}
/*
struct cmp
{
    bool operator()(pair<int,int> const &p) const
    {
        return p.first<p.second;
    }
};
*/
//struct cmp
//{
//    std::size_t operator()(const std::pair<int, int>& p) const {
//        return p.first ^ p.second;
//    }
//};

//struct cmp
//{
//    int operator()(const LL, int>& p) const {
//        return p.first < p.second;
//    }
//};
//struct Node
//{
//    int x,y,r;
//}cir[maxn];
vector<string> cir;
unordered_map<string,int> mp;
unordered_map<string,int> vis;
int n,m;
void dfs_Trave(int x,int y,int r);
void dfs(int x,int y,int r);
int main()
{
//    int a=123456789,b=123456;
//    int c=a&b;
//    cout << c << endl;

//    int a=123456789,b=45612;
//    cout << hash_val(a,b) << endl;

//    int a=122,b=456;
//    string s=to_string(a) +' ' +to_string(b);
//    cout << s << endl;
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        //cir[i]={x,y,r};
        LL val=hash_val(x);
        string temp=to_string(val)+' ' +to_string(y);
        cir.push_back(temp);
//        mp[temp]=r;
//        vis[temp]=0;
        auto it=mp.find(temp);
        if(it==mp.end())
        {
            vis[temp]=0;
            mp[temp]=r;
        }
        else
        {
            if(r>it->second)
                mp[temp]=r;
        }
    }

//    cout << "调试:\n";
//    for(auto val:mp)
//        cout << val.first << ' ' << val.second  << endl;
//    cout << "\ntiaoshi\n";
//    for(auto a:vis)
//        cout << a.first << ' ' << a.second << endl;
    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        dfs_Trave(x,y,r);
    }

//    cout << "\ntiaoshi2:\n";
//    for(auto a:vis)
//        cout << a.first << ' ' << a.second << endl;
    for(int i=0;i<n;++i)
    {
        auto temp=cir[i];
        if(vis[temp]!=0)
            ++res;
    }
    printf("%d\n",res);
    return 0;
}

void dfs(int x,int y,int r)
{
    LL val=hash_val(x);
    string temp=to_string(val) +' ' + to_string(y);
   // int x=index.first.first,y=index.first.second,r=index.second;
    vis[temp]=1;
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                LL val=hash_val(l);
                string temp=to_string(val)+' ' +to_string(s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(l,s,it->second);
                }
            }
        }

}

void dfs_Trave(int x,int y,int r)
{
    for(int l=x-r;l<=x+r;++l)
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                LL val=hash_val(l);
                string temp=to_string(val)+' ' + to_string(s);
                auto it=mp.find(temp);
                if(it!=mp.end())
                {
                    if(vis[temp]==0)
                        dfs(l,s,it->second);
                }
            }
        }
}

第十个,/**
    dfs实现图的遍历
    手写hash表:把每个点唯一表示一个值,然后存到一个数组中,由于最大值为1e9,
    所以可以把x坐标乘以一个(1e9+1)+y的坐标表示一个long long 值,也不会溢出,
    即表示为一个两位的进制数,不过这个进制是1e9+1;
    能AC;

*/

/**
    dfs实现图的遍历
    手写hash表:把每个点唯一表示一个值,然后存到一个数组中,由于最大值为1e9,
    所以可以把x坐标乘以一个(1e9+1)+y的坐标表示一个long long 值,也不会溢出,
    即表示为一个两位的进制数,不过这个进制是1e9+1;
    能AC;
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
using namespace std;

const int maxn=1e9,mod=7000003;
int test=999997;    //测试数是否为素数
typedef long long LL;
struct Node
{
    int x,y,r;
}cir[mod];
LL hs[mod]={0};
int id[mod]={0},vis[mod]={0};
int m,n;
void dfs(int x,int y,int r);
void dfs_Trave(int x,int y,int r);
LL hash_val(int x,int y)    //将二维坐标转换为一个hash值
{
    return (maxn+1ll)*x+y;
}

int hash_key(int x,int y)
{
    LL val=hash_val(x,y);
    int k=1,flag=-1;
    int key=(val%mod+mod)%mod;
    while(hs[key]!=-1&&hs[key]!=val)    //此处需要hs[key]!=key,因为后面需要查找用到二维坐标,
    {                                   //返回一个key值
        key+=k*k*flag;  //由于一个坐标最开始对应的key值也许被其他坐标占用了,这就需要查找
        ++k;            //一个没被用到的值,但考虑到一个值一个值的加,元素容易扎堆都被使用了,
        flag*=-1;       //于是我们就用平方探查法来查找
        key=(key%mod+mod)%mod;  //防止出现负值
    }
    return key;
}

LL squ(int x)
{
    return (LL) x*x;
}

void is_primer(int n)
{
    for(int i=2;i<=sqrt(n);++i)
        if(n%i==0)
        {
            cout << " not is primer ;\n";
            return;
        }
    cout << "is primer\n";
    return;
}

int main()
{
    is_primer(test);
    memset(hs,-1,sizeof(hs));
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        cir[i]={x,y,r};
        auto key=hash_key(x,y);
        if(hs[key]==-1) //这一个if语句需不需要都行
            hs[key]=hash_val(x,y);
        if(!id[key]||r>id[key]) //如果id[key]第一次被使用,或者此点的半径比之前的大,
            id[key]=r;          //那么更新这个点的半径
    }

    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        dfs_Trave(x,y,r);
    }

    for(int i=0;i<n;++i)
    {
        auto key=hash_key(cir[i].x,cir[i].y);
        if(vis[key]!=0)
            ++res;
    }
    printf("%d\n",res);
    return 0;
}

void dfs(int x,int y,int r)
{
    int key=hash_key(x,y);
    vis[key]=1;
    for(int l=x-r;l<=x+r;++l)   //遍历(x,y)周围可以炸到的所有点
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                int key=hash_key(l,s);
                if(hs[key]!=-1) //如果这个点处有炸弹
                {
                    if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
                        dfs(l,s,id[key]);
                }
            }
        }

}

void dfs_Trave(int x,int y,int r)
{
    for(int l=x-r;l<=x+r;++l)   //遍历(x,y)周围可以炸到的所有点
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                int key=hash_key(l,s);
                if(hs[key]!=-1) //如果这个点处有炸弹
                {
                    if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
                        dfs(l,s,id[key]);
                }
            }
        }
}

第十一个, 用BFS实现图的遍历,
    手写hash表:把每个点唯一表示一个值,然后存到一个数组中,由于最大值为1e9,
    所以可以把x坐标乘以一个(1e9+1)+y的坐标表示一个long long 值,也不会溢出,
    即表示为一个两位的进制数,不过这个进制是1e9+1;
    true coding,能AC

值得一提的是,vis[key]应当在进入bfs的队列便更新这个值已被访问,否则取出一个坐标的时候再更新,会导致一个点多次入队,浪费许多时间,acwing上最后一组数据超时,问题便出现在这儿

其实算法笔记讲解BFS的时候就已经强调了inq表示结点是否入队,而不是是否访问,这和DFS的vis数组是有区别的,当是还不以为然,觉得自己都理解了,现在想想,亦是惭愧!书你倒是看了,但你是否真正的吸收了呢?每学到一个算法,就要去找相应的题目来做,不然你也只是白白浪费时间,多了不说,算法笔记上的树状数组以及lowbit数组你现在是否还能知道它们的意思,KMP算法是否还有印象,快速排序是否还能写出来,组合数的知识还知道多少。。。等等,不光是低头做题,还得总结自己学到的东西,以后遇到能够用自己学过的算法解决的题目的时候,别两眼一蹬,我不会?那就从此处开始,把之前写的算法发成博客吧,也能再温习一遍。


/**
    用BFS实现图的遍历,
    手写hash表:把每个点唯一表示一个值,然后存到一个数组中,由于最大值为1e9,
    所以可以把x坐标乘以一个(1e9+1)+y的坐标表示一个long long 值,也不会溢出,
    即表示为一个两位的进制数,不过这个进制是1e9+1;
    true coding,能AC
*/
/**
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;

const int maxn=1e9,mod=700001,ne=50010;
int test=700001;    //测试数是否为素数
typedef long long LL;
struct Node
{
    int x,y,r;
}cir[ne];
LL hs[mod]={0};
int id[mod]={0},vis[mod]={0};
int m,n;
void bfs(Node zd);
void bfs_Trave(int x,int y,int r);
LL hash_val(int x,int y)    //将二维坐标转换为一个hash值
{
    return (maxn+1ll)*x+y;
}

int hash_key(int x,int y)
{
    LL val=hash_val(x,y);
    int k=1,flag=-1;
    int key=(val%mod+mod)%mod;
    while(hs[key]!=-1&&hs[key]!=val)    //此处需要hs[key]!=key,因为后面需要查找用到二维坐标,
    {                                   //返回一个key值
        key+=k*k*flag;  //由于一个坐标最开始对应的key值也许被其他坐标占用了,这就需要查找
        ++k;            //一个没被用到的值,但考虑到一个值一个值的加,元素容易扎堆都被使用了,
        flag*=-1;       //于是我们就用平方探查法来查找
        key=(key%mod+mod)%mod;  //防止出现负值
    }
    return key;
}

LL squ(int x)
{
    return (LL) x*x;
}

void is_primer(int n)
{
    for(int i=2;i<=sqrt(n);++i)
        if(n%i==0)
        {
            cout << " not is primer ;\n";
            return;
        }
    cout << "is primer\n";
    return;
}

int main()
{
    //is_primer(test);
    memset(hs,-1,sizeof(hs));
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        cir[i]={x,y,r};
        auto key=hash_key(x,y);
        if(hs[key]==-1) //这一个if语句需不需要都行
            hs[key]=hash_val(x,y);
        if(!id[key]||r>id[key]) //如果id[key]第一次被使用,或者此点的半径比之前的大,
            id[key]=r;          //那么更新这个点的半径
    }

    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        bfs_Trave(x,y,r);
    }

    for(int i=0;i<n;++i)
    {
        auto key=hash_key(cir[i].x,cir[i].y);
        if(vis[key]!=0)
            ++res;
    }
    printf("%d\n",res);
    return 0;
}

void bfs(Node zd)
{
    queue<Node> q;
    q.push(zd);
    while(!q.empty())
    {
        Node temp=q.front();
        int x=temp.x,y=temp.y,r=temp.r;
        q.pop();
        int key=hash_key(x,y);
       // vis[key]=1;
        for(int l=x-r;l<=x+r;++l)   //遍历(x,y)周围可以炸到的所有点
            for(int s=y+r;s>=y-r;--s)
            {
                if(squ(r) >= squ(l-x) + squ(s-y))
                {
                    int key=hash_key(l,s);
                    if(hs[key]!=-1) //如果这个点处有炸弹
                    {
                        if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
                        {
                            q.push({l,s,id[key]});
                            vis[key]=1; //值得一提的是,vis[key]应当在进入bfs的队列便更新这个值已被访问
                        }               //,否则取出一个坐标的时候再更新,会导致一个点多次入队
                    }                   //,浪费许多时间,acwing上最后一组数据超时,问题便出现在这儿
                }
            }
    }

}

void bfs_Trave(int x,int y,int r)
{
    for(int l=x-r;l<=x+r;++l)   //遍历(x,y)周围可以炸到的所有点
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                int key=hash_key(l,s);
                if(hs[key]!=-1) //如果这个点处有炸弹
                {
                    if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
                    {
                        vis[key]=1;
                        bfs({l,s,id[key]});
                    }
                }
            }
        }
}
*/

最后一个代码,是acwing上看的,因为我写的BFS始终由一组数据通不过,便对照着他的写,但还是有一组数据通不过,根本原因还是BFS入队的时候便要更新坐标已入队,否则会造成一个点多次入队,这一点必须谨记。和上一个一个代码唯一的不同便是这个id数组记录的是cir数组的下标,也就是存储在cir数组里的下标,上一个id存储的相同点的最大半径。

/**借鉴正确代码
*/

/**
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;

const int maxn=1e9,mod=1e6 + 7,ne=50010;
int test=700001;    //测试数是否为素数
typedef long long LL;
struct Node
{
    int x,y,r;
}cir[ne];
LL hs[mod]={0};
int id[mod]={0};    //id存储的是坐标在数组cir中对应的下标
bool vis[ne]={0};
int m,n;
void bfs(int index);
void bfs_Trave(int x,int y,int r);
LL hash_val(int x,int y)    //将二维坐标转换为一个hash值
{
    return (maxn+1ll)*x+y;
}

int hash_key(int x,int y)
{
    LL val=hash_val(x,y);
    int key=(val%mod+mod)%mod;
    while(hs[key]!=-1&&hs[key]!=val)    //此处需要hs[key]!=key,因为后面需要查找用到二维坐标,
    {                                   //返回一个key值
       key++;
        if(key == mod) key = 0;  //防止出现负值
    }
    return key;
}

LL squ(int x)
{
    return (LL) x*x;
}


int main()
{
    memset(hs,-1,sizeof(hs));
    scanf("%d%d",&n,&m);
    int x,y,r;
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        cir[i]={x,y,r};
        auto key=hash_key(x,y);
        if(hs[key]==-1) //这一个if语句需不需要都行
            hs[key]=hash_val(x,y);
        if(!id[key]||r>cir[id[key]].r) //如果id[key]第一次被使用,或者此点的半径比之前的大,
            id[key]=i;          //那么更新这个点的坐标下标
    }

    int res=0;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&x,&y,&r);
        bfs_Trave(x,y,r);
    }

    for(int i=1;i<=n;++i)
    {
        auto key=hash_key(cir[i].x,cir[i].y);
        int pos=id[key];
        if(pos&&vis[pos])
            ++res;
    }
    printf("%d\n",res);
    return 0;
}

void bfs(int index)
{
    queue<int> q;
    q.push(index);
    vis[index]=1;
    while(!q.empty())
    {
        int temp=q.front();
        int x=cir[temp].x,y=cir[temp].y,r=cir[temp].r;
        q.pop();
        //int key=hash_key(x,y);
        //vis[temp]=1;  //在这儿将temp号的值赋为1便是错的,不知道原因
        for(int l=x-r;l<=x+r;++l)   //遍历(x,y)周围可以炸到的所有点
            for(int s=y+r;s>=y-r;--s)
            {
                if(squ(r) >= squ(l-x) + squ(s-y))
                {
                    int key=hash_key(l,s);
                    if(id[key]&&!vis[id[key]]) //如果这个点处有炸弹
                    {
                        int pos=id[key];//如果这个点处的炸弹没被拆除掉
                            q.push(pos);
                            vis[pos]=1;
                    }
                }
            }
    }

}

void bfs_Trave(int x,int y,int r)
{
    for(int l=x-r;l<=x+r;++l)   //遍历(x,y)周围可以炸到的所有点
        for(int s=y+r;s>=y-r;--s)
        {
            if(squ(r) >= squ(l-x) + squ(s-y))
            {
                int key=hash_key(l,s);
                if(id[key]&&!vis[id[key]]) //如果这个点处有炸弹
                {                    //如果这个点处的炸弹没被拆除掉
                        bfs(id[key]);
                }
            }
        }
}

有关蓝桥杯2022初赛——扫雷的更多相关文章

  1. 映宇宙2022年营收63亿元:同比下降三成,毛利率提升4.3个百分点 - 2

    3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升

  2. 蓝桥杯备赛(二) - 2

    目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言:  在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC  已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析  这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy

  3. 蓝桥杯C/C++VIP试题每日一练之报时助手 - 2

    ?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是:  如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。  如果m不为0,则将时读出来,然后将分读出来,如5

  4. IDEA 2022 创建 Spring Boot 项目详解 - 2

    如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1.  创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1.  创建SpringBoot项目        打开IDEA,选择NewProject创建项目。        填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。        选择springboot版本以及需要的包,此处只选择了springweb。        此处需特别注意,若你使用的是jdk1

  5. 十四届蓝桥青少组模拟赛Python-20221108 - 2

    十四届蓝桥青少组模拟赛Python-20221108T1.二进制位数十进制整数2在十进制中是1位数,在二进制中对应10,是2位数。十进制整数22在十进制中是2位数,在二进制中对应10110,是5位数。请问十进制整数2022在二进制中是几位数?print(len(bin(2022))-2)#运行结果:11T2.晨跑小蓝每周六、周日都晨跑,每月的1、11、21、31日也晨跑。其它时间不晨跑。已知2022年1月1日是周六,请问小蓝整个2022年晨跑多少天?#样例代码1ls=[0,31,28,31,30,31,30,31,31,30,31,30,31]ans=0k=6foriinrange(1,13)

  6. 2022年10月23日周赛ZZULIOJ - 2

    文章目录问题B:芝华士威士忌和他的小猫咪们代码&注释问题C:愿我的弹雨能熄灭你们的痛苦代码注释问题D:猜糖果游戏代码注释问题E:有趣的次方代码注释问题F:这是一个简单题代码&注释问题G:打印矩阵代码注释问题H:scz的简单考验代码注释问题I:完美区间代码&注释问题J:是狂热的小迷妹一枚吖~代码&注释2022年10月23日周赛ZZULIOJ问题B:芝华士威士忌和他的小猫咪们时间限制:1Sec内存限制:128MB题目描述芝华士威士忌很喜欢带着他的猫咪们一块跑着玩。但是小猫咪们很懒,只有在离他y米以内才愿意和他一块跑。这天他在坐标为x的位置,他想和他的猫咪们一块跑着玩。有n个小猫咪,第i个小猫咪在坐

  7. 【华为OD机试真题 java、python、c++】荒地电站建设【2022 Q4 100分】(100%通过+复盘思路) - 2

    代码请进行一定修改后使用,本代码保证100%通过率,本题目提供了java、python、c++三种代码。复盘思路在文章的最后题目描述祖国西北部有一片大片荒地,其中零星的分布着一些湖泊,保护区,矿区;整体上常年光照良好,但是也有一些地区光照不太好。某电力公司希望在这里建设多个光伏电站,生产清洁能源对每平方公里的土地进行了发电评估,其中不能建设的区域发电量为0kw,可以发电的区域根据光照,地形等给出了每平方公里年发电量x千瓦。我们希望能够找到其中集中的矩形区域建设电站,能够获得良好的收益。输入描述第一行输入为调研的地区长,宽,以及准备建设的电站【长宽相等,为正方形】的边长最低要求的发电量之后每行为

  8. 蓝桥杯 stm32 MCP4017 - 2

    本文代码使用HAL库。文章目录前言一、MCP4017的重要特性二、MCP4017计算RBW阻值三、MCP4017地址四、MCP4017读写函数五、CubeMX创建工程(利用ADC测量MCP4017电压)、对应代码:总结前言一、MCP4017的重要特性蓝桥杯板子上的是MCP4017T-104ELT,如图1。MCP4017是一个可编程电阻,通过写入的数值可以改变电阻的大小。重点在于6引脚(W),5引脚(B&#

  9. [蓝桥杯单片机]学习笔记——串口通信的基本原理与应用 - 2

    目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式  2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器​编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置  3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一

  10. 玩客云刷机(2022-3-19亲测) - 2

    https://cloud.189.cn/t/BJbYreYbmUj2(访问码:djz6)(网盘2022-4-1更新)一、刷入armbian。1.1使用AmlBurnTool软件烧录首选底包至固件。烧录完成后断开玩客云电源备用。(靠近hdmi的那个口子。)1.2使用WIn32diskimager软件将emmc固件写入U盘。1.3写入成功后,先将U盘插入玩客云靠近网线接口端的USB口,再接入电源。玩客云通电后指示灯会先亮绿灯,再亮蓝灯,红蓝闪烁,最后蓝灯常亮。等到确定蓝灯常亮后,再拔掉U盘、电源。(最好蓝灯常亮后,启动一次玩客云,看看ssh是否正常。)1.4使用WIn32diskimager写入

随机推荐