• 蓝桥杯2022初赛——扫雷


    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

    输入样例:

    1. 2 1
    2. 2 2 4
    3. 4 4 2
    4. 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,  明显会超时。

    1. /**
    2. 图的深度优先遍历,邻接表实现
    3. 由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    4. 明显会超时
    5. */
    6. /**
    7. #include <iostream>
    8. #include <cstdio>
    9. #include <cmath>
    10. #include <vector>
    11. using namespace std;
    12. const int maxn=1010;
    13. struct Node
    14. {
    15. int x,y,r;
    16. }cir[maxn];
    17. vector<int> adj[maxn];
    18. bool vis[maxn]={false};
    19. int n,m;
    20. int dfs_Trave(int x,int y,int r);
    21. int dfs(int index);
    22. void add(int index);
    23. int main()
    24. {
    25. scanf("%d%d",&n,&m);
    26. int x,y,r;
    27. for(int i=0;i<n;++i)
    28. {
    29. scanf("%d%d%d",&x,&y,&r);
    30. cir[i]={x,y,r};
    31. }
    32. for(int i=0;i<n;++i)
    33. {
    34. add(i);
    35. }
    36. // cout << "调试:\n";
    37. // for(int i=0;i<n;++i)
    38. // {
    39. // for(auto b:adj[i])
    40. // cout << b << ' ';
    41. // cout << endl;
    42. // }
    43. // cout << "jk\n";
    44. int res=0;
    45. for(int i=0;i<m;++i)
    46. {
    47. scanf("%d%d%d",&x,&y,&r);
    48. // cout << "r:" << r << endl;
    49. //printf("r:%d\n",r);
    50. res+=dfs_Trave(x,y,r);
    51. }
    52. printf("%d\n",res);
    53. return 0;
    54. }
    55. void add(int index)
    56. {
    57. for(int i=0;i<n;++i)
    58. if(i!=index)
    59. {
    60. if(cir[index].r>(sqrt(pow(cir[i].x-cir[index].x,2)+pow(cir[i].y-cir[index].y,2))))
    61. adj[index].push_back(i);
    62. }
    63. }
    64. int dfs(int index)
    65. {
    66. //cout << "jinbulai?\n";
    67. int sum=1;
    68. vis[index]=true;
    69. for(int i=0;i<adj[index].size();++i)
    70. {
    71. int v=adj[index][i];
    72. if(vis[v]==false)
    73. sum+=dfs(v);
    74. }
    75. return sum;
    76. }
    77. int dfs_Trave(int x,int y,int r)
    78. {
    79. // cout << "r:" << r << endl;
    80. int sum=0;
    81. for(int i=0;i<n;++i)
    82. {
    83. double L=sqrt(pow(x-cir[i].x,2)+pow(y-cir[i].y,2));
    84. // cout << "length:" << L << endl;
    85. if(r>L)
    86. {
    87. // cout << "error: \n";
    88. if(vis[i]==false)
    89. sum+=dfs(i);
    90. }
    91. }
    92. return sum;
    93. }

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

    1. /**
    2. 图的深度优先遍历,邻接表实现
    3. 由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    4. 先把坐标按x轴从小到大排序,再按y轴从小到大排序
    5. acwing 最后一组数据通不过,最开始的时候始终找不出原因,现在想想,也能理解,
    6. 当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    7. 不然建图的时候有O(n^2)的时间复杂度。
    8. 下一个代码我给出了AC的代码;
    9. */
    10. /**
    11. #include <iostream>
    12. #include <cstdio>
    13. #include <cmath>
    14. #include <algorithm>
    15. #include <vector>
    16. #include <unordered_map>
    17. using namespace std;
    18. const int maxn=50010;
    19. struct Node
    20. {
    21. int x,y,r;
    22. int cnt;
    23. Node (int _x,int _y) : x(_x),y(_y){}
    24. Node (int _x,int _y,int _r) : x(_x),y(_y),r(_r){}
    25. Node (int _x,int _y,int _r,int _cnt) :x(_x),y(_y),r(_r),cnt(_cnt){}
    26. Node()=default;
    27. bool operator < (Node const & a) const
    28. {
    29. if(x!=a.x)
    30. return x<a.x;
    31. return y<a.y;
    32. }
    33. }cir[maxn];
    34. struct comp
    35. {
    36. int operator()(const std::pair<int, int>& p) const {
    37. return p.first ^ p.second; //返回值为bool,比较符为&,|都比这一个慢,
    38. }
    39. };
    40. typedef long long LL;
    41. LL squ(int x)
    42. {
    43. return (LL) x*x;
    44. }
    45. vector<int> adj[maxn];
    46. unordered_map<pair<int,int> ,int,comp> ump;
    47. bool vis[maxn]={false};
    48. int n,m;
    49. int dfs_Trave(int x,int y,int r);
    50. int dfs(int index);
    51. void add(int index);
    52. int main()
    53. {
    54. scanf("%d%d",&n,&m);
    55. int x,y,r;
    56. for(int i=1;i<=n;++i)
    57. {
    58. scanf("%d%d%d",&x,&y,&r);
    59. auto temp=ump[{x,y}];
    60. if(temp!=0)
    61. {
    62. cir[temp].r=max(cir[temp].r,r);
    63. cir[temp].cnt++;
    64. }
    65. else
    66. {
    67. cir[i]={x,y,r,1}; //应当用一个全局变量来表示不重复点的下标
    68. ump[{x,y}]=i; //
    69. }
    70. }
    71. sort(cir+1,cir+n+1);
    72. // Node temp={2,3,9};
    73. // auto it=lower_bound(cir+1,cir+n+1,temp);
    74. // cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
    75. // Node temp2={2,50,9};
    76. // it=lower_bound(cir+1,cir+n+1,temp2);
    77. // cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
    78. // cout << "调试:\n";
    79. // for(int i=1;i<=n;++i)
    80. // cout << cir[i].x << ' ' << cir[i].y << ' ' << cir[i].r << endl;
    81. // cout << "ok\n";
    82. for(int i=1;i<=n;++i)
    83. {
    84. add(i);
    85. }
    86. // cout << "调试:\n";
    87. // for(int i=0;i<n;++i)
    88. // {
    89. // for(auto b:adj[i])
    90. // cout << b << ' ';
    91. // cout << endl;
    92. // }
    93. // cout << "jk\n";
    94. int res=0;
    95. for(int i=0;i<m;++i)
    96. {
    97. scanf("%d%d%d",&x,&y,&r);
    98. // cout << "r:" << r << endl;
    99. //printf("r:%d\n",r);
    100. res+=dfs_Trave(x,y,r);
    101. }
    102. printf("%d\n",res);
    103. return 0;
    104. }
    105. void add(int index)
    106. {
    107. for(int i=index-1;i>0;--i)
    108. {
    109. if(squ(cir[index].r)<squ(cir[i].x-cir[index].x))
    110. break;
    111. if(squ(cir[index].r)>=squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
    112. adj[index].push_back(i);
    113. }
    114. for(int i=index+1;i<=n;++i)
    115. {
    116. if(squ(cir[index].r) < squ(cir[i].x-cir[index].x))
    117. break;
    118. if(squ(cir[index].r) >= squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
    119. adj[index].push_back(i);
    120. }
    121. }
    122. int dfs(int index)
    123. {
    124. int sum=cir[index].cnt;
    125. vis[index]=1;
    126. for(int i=0;i<adj[index].size();++i)
    127. {
    128. int v=adj[index][i];
    129. if(vis[v]==0)
    130. sum+=dfs(v);
    131. }
    132. return sum;
    133. }
    134. int dfs_Trave(int x,int y,int r)
    135. {
    136. Node e1={x-r,y,r},e2={x+r,y,r};
    137. int l=lower_bound(cir+1,cir+n+1,e1)-cir;
    138. int ri=lower_bound(cir+1,cir+n+1,e2)-cir;
    139. l=min(l,n),ri=min(ri,n);
    140. int sum=0;
    141. for(int i=l;i<=ri;++i)
    142. {
    143. if(i==0)
    144. continue;
    145. if((squ(r)>=squ(cir[i].x-x)+squ(cir[i].y-y))&&vis[i]==0)
    146. sum+=dfs(i);
    147. }
    148. return sum;
    149. }

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

    1. /**
    2. 图的深度优先遍历,邻接表实现
    3. 由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    4. 先把坐标按x轴从小到大排序,再按y轴从小到大排序
    5. 当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    6. 不然建图的时候有O(n^2)的时间复杂度。
    7. 能AC
    8. */
    9. /**
    10. #include <iostream>
    11. #include <cstdio>
    12. #include <cmath>
    13. #include <algorithm>
    14. #include <vector>
    15. #include <unordered_map>
    16. using namespace std;
    17. const int maxn=50010;
    18. struct Node
    19. {
    20. int x,y,r;
    21. int cnt;
    22. Node (int _x,int _y) : x(_x),y(_y){}
    23. Node (int _x,int _y,int _r) : x(_x),y(_y),r(_r){}
    24. Node (int _x,int _y,int _r,int _cnt) :x(_x),y(_y),r(_r),cnt(_cnt){}
    25. Node()=default;
    26. bool operator < (Node const & a) const
    27. {
    28. if(x!=a.x)
    29. return x<a.x;
    30. return y<a.y;
    31. }
    32. }cir[maxn];
    33. struct comp
    34. {
    35. int operator()(const std::pair<int, int>& p) const {
    36. return p.first ^ p.second; //返回值为bool,比较符为&,|都比这一个慢,
    37. }
    38. };
    39. typedef long long LL;
    40. LL squ(int x)
    41. {
    42. return (LL) x*x;
    43. }
    44. vector<int> adj[maxn];
    45. unordered_map<pair<int,int> ,int,comp> ump; //实践上机证明将坐标转化为long long 比这种方式快上一点
    46. bool vis[maxn]={false};
    47. int n,m,n1=0;
    48. int dfs_Trave(int x,int y,int r);
    49. int dfs(int index);
    50. void add(int index);
    51. int main()
    52. {
    53. scanf("%d%d",&n,&m);
    54. int x,y,r;
    55. for(int i=1;i<=n;++i)
    56. {
    57. scanf("%d%d%d",&x,&y,&r);
    58. auto temp=ump[{x,y}];
    59. if(temp!=0)
    60. {
    61. cir[temp].r=max(cir[temp].r,r);
    62. cir[temp].cnt++;
    63. }
    64. else
    65. {
    66. cir[++n1]={x,y,r,1};
    67. ump[{x,y}]=n1;
    68. // cir[i].cnt=1;
    69. }
    70. }
    71. sort(cir+1,cir+n1+1);
    72. // Node temp={2,3,9};
    73. // auto it=lower_bound(cir+1,cir+n+1,temp);
    74. // cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
    75. // Node temp2={2,50,9};
    76. // it=lower_bound(cir+1,cir+n+1,temp2);
    77. // cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
    78. // cout << "调试:\n";
    79. // for(int i=1;i<=n;++i)
    80. // cout << cir[i].x << ' ' << cir[i].y << ' ' << cir[i].r << endl;
    81. // cout << "ok\n";
    82. for(int i=1;i<=n1;++i)
    83. {
    84. add(i);
    85. }
    86. int res=0;
    87. for(int i=0;i<m;++i)
    88. {
    89. scanf("%d%d%d",&x,&y,&r);
    90. res+=dfs_Trave(x,y,r);
    91. }
    92. printf("%d\n",res);
    93. return 0;
    94. }
    95. void add(int index)
    96. {
    97. for(int i=index-1;i>0;--i)
    98. {
    99. if(squ(cir[index].r)<squ(cir[i].x-cir[index].x))
    100. break;
    101. if(squ(cir[index].r)>=squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
    102. adj[index].push_back(i);
    103. }
    104. for(int i=index+1;i<=n1;++i)
    105. {
    106. if(squ(cir[index].r) < squ(cir[i].x-cir[index].x))
    107. break;
    108. if(squ(cir[index].r) >= squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
    109. adj[index].push_back(i);
    110. }
    111. }
    112. int dfs(int index)
    113. {
    114. int sum=cir[index].cnt;
    115. vis[index]=1;
    116. for(int i=0;i<adj[index].size();++i)
    117. {
    118. int v=adj[index][i];
    119. if(vis[v]==0)
    120. sum+=dfs(v);
    121. }
    122. return sum;
    123. }
    124. int dfs_Trave(int x,int y,int r)
    125. {
    126. Node e1={x-r,y,r},e2={x+r,y,r};
    127. int l=lower_bound(cir+1,cir+n1+1,e1)-cir;
    128. int ri=lower_bound(cir+1,cir+n1+1,e2)-cir;
    129. l=min(l,n1),ri=min(ri,n1);
    130. int sum=0;
    131. for(int i=l;i<=ri;++i)
    132. {
    133. if(i==0)
    134. continue;
    135. if((squ(r)>=squ(cir[i].x-x)+squ(cir[i].y-y))&&vis[i]==0)
    136. sum+=dfs(i);
    137. }
    138. return sum;
    139. }

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

    1. /**
    2. 图的广度优先遍历,邻接表实现
    3. 由于点数有1e5,那么遍历所有图上的点是否联通,需要O(n^2)也就是需要2.5e9,
    4. 先把坐标按x轴从小到大排序,再按y轴从小到大排序
    5. 当许多坐标扎堆在同一点的时候,应当去掉重复的点,只留下半径最大的点。
    6. 不然建图的时候有O(n^2)的时间复杂度。
    7. 能AC
    8. */
    9. #include <iostream>
    10. #include <cstdio>
    11. #include <cmath>
    12. #include <algorithm>
    13. #include <vector>
    14. #include <queue>
    15. #include <unordered_map>
    16. using namespace std;
    17. const int maxn=50010;
    18. struct Node
    19. {
    20. int x,y,r;
    21. int cnt;
    22. Node (int _x,int _y) : x(_x),y(_y){}
    23. Node (int _x,int _y,int _r) : x(_x),y(_y),r(_r){}
    24. Node (int _x,int _y,int _r,int _cnt) :x(_x),y(_y),r(_r),cnt(_cnt){}
    25. Node()=default;
    26. bool operator < (Node const & a) const
    27. {
    28. if(x!=a.x)
    29. return x<a.x;
    30. return y<a.y;
    31. }
    32. }cir[maxn];
    33. struct comp
    34. {
    35. int operator()(const std::pair<int, int>& p) const {
    36. return p.first ^ p.second; //返回值为bool,比较符为&,|都比这一个慢,
    37. }
    38. };
    39. typedef long long LL;
    40. LL squ(int x)
    41. {
    42. return (LL) x*x;
    43. }
    44. vector<int> adj[maxn];
    45. unordered_map<pair<int,int> ,int,comp> ump; //实践上机证明将坐标转化为long long 比这种方式快上一点
    46. bool vis[maxn]={false};
    47. int n,m,n1=0;
    48. int bfs_Trave(int x,int y,int r);
    49. int bfs(int index);
    50. void add(int index);
    51. int main()
    52. {
    53. scanf("%d%d",&n,&m);
    54. int x,y,r;
    55. for(int i=1;i<=n;++i)
    56. {
    57. scanf("%d%d%d",&x,&y,&r);
    58. auto temp=ump[{x,y}];
    59. if(temp!=0)
    60. {
    61. cir[temp].r=max(cir[temp].r,r);
    62. cir[temp].cnt++;
    63. }
    64. else
    65. {
    66. cir[++n1]={x,y,r,1};
    67. ump[{x,y}]=n1;
    68. // cir[i].cnt=1;
    69. }
    70. }
    71. sort(cir+1,cir+n1+1);
    72. // Node temp={2,3,9};
    73. // auto it=lower_bound(cir+1,cir+n+1,temp);
    74. // cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
    75. // Node temp2={2,50,9};
    76. // it=lower_bound(cir+1,cir+n+1,temp2);
    77. // cout << "tiaoshi: " << it->x << ' ' << it->y << ' ' << it->r << endl;
    78. // cout << "调试:\n";
    79. // for(int i=1;i<=n;++i)
    80. // cout << cir[i].x << ' ' << cir[i].y << ' ' << cir[i].r << endl;
    81. // cout << "ok\n";
    82. for(int i=1;i<=n1;++i)
    83. {
    84. add(i);
    85. }
    86. int res=0;
    87. for(int i=0;i<m;++i)
    88. {
    89. scanf("%d%d%d",&x,&y,&r);
    90. res+=bfs_Trave(x,y,r);
    91. }
    92. printf("%d\n",res);
    93. return 0;
    94. }
    95. void add(int index)
    96. {
    97. for(int i=index-1;i>0;--i)
    98. {
    99. if(squ(cir[index].r)<squ(cir[i].x-cir[index].x))
    100. break;
    101. if(squ(cir[index].r)>=squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
    102. adj[index].push_back(i);
    103. }
    104. for(int i=index+1;i<=n1;++i)
    105. {
    106. if(squ(cir[index].r) < squ(cir[i].x-cir[index].x))
    107. break;
    108. if(squ(cir[index].r) >= squ(cir[i].x-cir[index].x)+squ(cir[i].y-cir[index].y))
    109. adj[index].push_back(i);
    110. }
    111. }
    112. int bfs(int index)
    113. {
    114. queue<int> q;
    115. q.push(index);
    116. int sum=cir[index].cnt;
    117. while(!q.empty())
    118. {
    119. int top=q.front();
    120. q.pop();
    121. for(int i=0;i<adj[top].size();++i)
    122. {
    123. int v=adj[top][i];
    124. if(vis[v]==0)
    125. {
    126. vis[v]=1;
    127. sum+=cir[v].cnt;
    128. q.push(v);
    129. }
    130. }
    131. }
    132. return sum;
    133. }
    134. int bfs_Trave(int x,int y,int r)
    135. {
    136. Node e1={x-r,y,r},e2={x+r,y,r};
    137. int l=lower_bound(cir+1,cir+n1+1,e1)-cir;
    138. int ri=lower_bound(cir+1,cir+n1+1,e2)-cir;
    139. l=min(l,n1),ri=min(ri,n1);
    140. int sum=0;
    141. for(int i=l;i<=ri;++i)
    142. {
    143. if(i==0)
    144. continue;
    145. if((squ(r)>=squ(cir[i].x-x)+squ(cir[i].y-y))&&vis[i]==0)
    146. {
    147. vis[i]=1;
    148. sum+=bfs(i);
    149. }
    150. }
    151. return sum;
    152. }

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

    1. /**
    2. map,将坐标用pair<int,int>存在map
    3. */
    4. /**
    5. 1)每输入一个排雷火箭,就算出它排掉了多少雷,但是由于一个位置有多个雷
    6. ,所以要把这个位置的地雷数给记录下来;
    7. acwing通过5/11
    8. */
    9. /**
    10. #include <iostream>
    11. #include <cstdio>
    12. #include <cmath>
    13. #include <vector>
    14. #include <map>
    15. using namespace std;
    16. typedef long long LL;
    17. LL squ(int x)
    18. {
    19. return (LL) x*x;
    20. }
    21. map<pair<int,int>,pair<int,int> > mp;
    22. map<pair<int,int>,int > vis;
    23. int n,m;
    24. int dfs_Trave(int x,int y,int r);
    25. int dfs(pair<pair<int,int>,pair<int,int> > index);
    26. int main()
    27. {
    28. scanf("%d%d",&n,&m);
    29. int x,y,r;
    30. for(int i=0;i<n;++i)
    31. {
    32. scanf("%d%d%d",&x,&y,&r);
    33. auto temp=make_pair(x,y);
    34. auto it=mp.find(temp);
    35. if(it==mp.end())
    36. {
    37. vis[temp]=0;
    38. auto val=make_pair(r,1);
    39. mp[temp]=val;
    40. }
    41. else
    42. {
    43. if(r>it->second.first)
    44. {
    45. auto val=make_pair(r,it->second.second+1);
    46. mp[temp]=val;
    47. }
    48. else
    49. {
    50. auto val=make_pair(it->second.first,it->second.second+1);
    51. mp[temp]=val;
    52. }
    53. }
    54. }
    55. int res=0;
    56. for(int i=0;i<m;++i)
    57. {
    58. scanf("%d%d%d",&x,&y,&r);
    59. res+=dfs_Trave(x,y,r);
    60. }
    61. printf("%d\n",res);
    62. return 0;
    63. }
    64. int dfs(pair<pair<int,int>,pair<int,int> > index)
    65. {
    66. int x=index.first.first,y=index.first.second,r=index.second.first,num=index.second.second;
    67. int sum=num;
    68. //cout << "调试:" << sum << endl;
    69. vis[index.first]=1;
    70. for(int l=x-r;l<=x+r;++l)
    71. for(int s=y+r;s>=y-r;--s)
    72. {
    73. if(squ(r) >= squ(l-x) + squ(s-y))
    74. {
    75. auto temp=make_pair(l,s);
    76. auto it=mp.find(temp);
    77. if(it!=mp.end())
    78. {
    79. if(vis[temp]==0)
    80. sum+=dfs(*it);
    81. }
    82. }
    83. }
    84. return sum;
    85. }
    86. int dfs_Trave(int x,int y,int r)
    87. {
    88. int sum=0;
    89. for(int l=x-r;l<=x+r;++l)
    90. for(int s=y+r;s>=y-r;--s)
    91. {
    92. if(squ(r) >= squ(l-x) + squ(s-y))
    93. {
    94. auto temp=make_pair(l,s);
    95. auto it=mp.find(temp);
    96. if(it!=mp.end())
    97. {
    98. if(vis[temp]==0)
    99. sum+=dfs(*it);
    100. }
    101. }
    102. }
    103. return sum;
    104. }
    105. */

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

    1. /**
    2. 2)先把排掉的雷给记录下来,最后统一计算,只记录半径,不用记录每个位置有多少雷;
    3. 当相应的就需要把所有的地雷的位置给记录下来,即使他们是相同的位置这就是cir数组的作用
    4. acwing也是通过5/11
    5. */
    6. /**
    7. #include <iostream>
    8. #include <cstdio>
    9. #include <cmath>
    10. #include <vector>
    11. #include <map>
    12. using namespace std;
    13. typedef long long LL;
    14. LL squ(int x)
    15. {
    16. return (LL) x*x;
    17. }
    18. const int maxn=50010;
    19. struct Node
    20. {
    21. int x,y,r;
    22. }cir[maxn];
    23. map<pair<int,int>,int > mp;
    24. map<pair<int,int>,int > vis;
    25. int n,m;
    26. void dfs_Trave(int x,int y,int r);
    27. void dfs(pair<pair<int,int>,int > index);
    28. int main()
    29. {
    30. scanf("%d%d",&n,&m);
    31. int x,y,r;
    32. for(int i=0;i<n;++i)
    33. {
    34. scanf("%d%d%d",&x,&y,&r);
    35. cir[i]={x,y,r};
    36. auto temp=make_pair(x,y);
    37. auto it=mp.find(temp);
    38. if(it==mp.end())
    39. {
    40. vis[temp]=0;
    41. mp[temp]=r;
    42. }
    43. else
    44. {
    45. if(r>it->second)
    46. mp[temp]=r;
    47. }
    48. }
    49. int res=0;
    50. for(int i=0;i<m;++i)
    51. {
    52. scanf("%d%d%d",&x,&y,&r);
    53. dfs_Trave(x,y,r);
    54. }
    55. for(int i=0;i<n;++i)
    56. {
    57. auto temp=make_pair(cir[i].x,cir[i].y);
    58. if(vis[temp]!=0)
    59. ++res;
    60. }
    61. printf("%d\n",res);
    62. return 0;
    63. }
    64. void dfs(pair<pair<int,int>,int > index)
    65. {
    66. int x=index.first.first,y=index.first.second,r=index.second;
    67. vis[index.first]=1;
    68. for(int l=x-r;l<=x+r;++l)
    69. for(int s=y+r;s>=y-r;--s)
    70. {
    71. if(squ(r) >= squ(l-x) + squ(s-y))
    72. {
    73. auto temp=make_pair(l,s);
    74. auto it=mp.find(temp);
    75. if(it!=mp.end())
    76. {
    77. if(vis[temp]==0)
    78. dfs(*it);
    79. }
    80. }
    81. }
    82. }
    83. void dfs_Trave(int x,int y,int r)
    84. {
    85. for(int l=x-r;l<=x+r;++l)
    86. for(int s=y+r;s>=y-r;--s)
    87. {
    88. if(squ(r) >= squ(l-x) + squ(s-y))
    89. {
    90. auto temp=make_pair(l,s);
    91. auto it=mp.find(temp);
    92. if(it!=mp.end())
    93. {
    94. if(vis[temp]==0)
    95. dfs(*it);
    96. }
    97. }
    98. }
    99. }
    100. */

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

    1. /**
    2. unorder_map解决,将坐标用pair<int,int>存在unordered_map中
    3. */
    4. /**
    5. 1)对于没有默认的哈希函数的类型,如自定义的 class 类型,pair 类型等,我们就必须自己
    6. 指定一个哈希函数。这也是为什么直接构建 pair 类型的 unordered_set
    7. 如 unordered_set<pair<int, int>> uset 会出现问题
    8. acwing通过5/11
    9. */
    10. #include <iostream>
    11. #include <cstdio>
    12. #include <cmath>
    13. #include <vector>
    14. #include <unordered_map>
    15. using namespace std;
    16. typedef long long LL;
    17. LL squ(int x)
    18. {
    19. return (LL) x*x;
    20. }
    21. const int maxn=50010;
    22. /*
    23. struct cmp
    24. {
    25. bool operator()(pair<int,int> const &p) const
    26. {
    27. return p.first<p.second;
    28. }
    29. };
    30. */
    31. //struct cmp
    32. //{
    33. // std::size_t operator()(const std::pair<int, int>& p) const {
    34. // return p.first ^ p.second;
    35. // }
    36. //};
    37. struct cmp
    38. {
    39. int operator()(const std::pair<int, int>& p) const {
    40. return p.first ^ p.second; //返回值为bool,比较符为&,|都比这一个慢,
    41. }
    42. };
    43. struct Node
    44. {
    45. int x,y,r;
    46. }cir[maxn];
    47. unordered_map<pair<int,int>,int ,cmp> mp;
    48. unordered_map<pair<int,int>,int ,cmp> vis;
    49. int n,m;
    50. void dfs_Trave(int x,int y,int r);
    51. void dfs(pair<pair<int,int>,int > index);
    52. int main()
    53. {
    54. // int a=123456789,b=123456;
    55. // int c=a&b;
    56. // cout << c << endl;
    57. scanf("%d%d",&n,&m);
    58. int x,y,r;
    59. for(int i=0;i<n;++i)
    60. {
    61. scanf("%d%d%d",&x,&y,&r);
    62. cir[i]={x,y,r};
    63. auto temp=make_pair(x,y);
    64. auto it=mp.find(temp);
    65. if(it==mp.end())
    66. {
    67. vis[temp]=0;
    68. mp[temp]=r;
    69. }
    70. else
    71. {
    72. if(r>it->second)
    73. mp[temp]=r;
    74. }
    75. }
    76. /*
    77. cout << "调试:\n";
    78. for(auto val:mp)
    79. cout << val.first.first << ' ' << val.first.second << ' ' << val.second << endl;
    80. */
    81. int res=0;
    82. for(int i=0;i<m;++i)
    83. {
    84. scanf("%d%d%d",&x,&y,&r);
    85. dfs_Trave(x,y,r);
    86. }
    87. for(int i=0;i<n;++i)
    88. {
    89. auto temp=make_pair(cir[i].x,cir[i].y);
    90. if(vis[temp]!=0)
    91. ++res;
    92. }
    93. printf("%d\n",res);
    94. return 0;
    95. }
    96. void dfs(pair<pair<int,int>,int > index)
    97. {
    98. int x=index.first.first,y=index.first.second,r=index.second;
    99. vis[index.first]=1;
    100. for(int l=x-r;l<=x+r;++l)
    101. for(int s=y+r;s>=y-r;--s)
    102. {
    103. if(squ(r) >= squ(l-x) + squ(s-y))
    104. {
    105. auto temp=make_pair(l,s);
    106. auto it=mp.find(temp);
    107. if(it!=mp.end())
    108. {
    109. if(vis[temp]==0)
    110. dfs(*it);
    111. }
    112. }
    113. }
    114. }
    115. void dfs_Trave(int x,int y,int r)
    116. {
    117. for(int l=x-r;l<=x+r;++l)
    118. for(int s=y+r;s>=y-r;--s)
    119. {
    120. if(squ(r) >= squ(l-x) + squ(s-y))
    121. {
    122. auto temp=make_pair(l,s);
    123. auto it=mp.find(temp);
    124. if(it!=mp.end())
    125. {
    126. if(vis[temp]==0)
    127. dfs(*it);
    128. }
    129. }
    130. }
    131. }

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

    1. /**
    2. 将坐标转换为一个long long数值,存在unorder_map中;
    3. acwing通过了6/11;
    4. */
    5. #include <iostream>
    6. #include <cstdio>
    7. #include <cmath>
    8. #include <vector>
    9. #include <string>
    10. #include <unordered_map>
    11. using namespace std;
    12. typedef long long LL;
    13. LL squ(int x)
    14. {
    15. return (LL) x*x;
    16. }
    17. const int maxn=50010,inf=1e9;
    18. LL hash_val(int x,int y)
    19. {
    20. return x*(inf+1ll)+y;
    21. }
    22. /*
    23. struct cmp
    24. {
    25. bool operator()(pair<int,int> const &p) const
    26. {
    27. return p.first<p.second;
    28. }
    29. };
    30. */
    31. //struct cmp
    32. //{
    33. // std::size_t operator()(const std::pair<int, int>& p) const {
    34. // return p.first ^ p.second;
    35. // }
    36. //};
    37. //struct cmp
    38. //{
    39. // int operator()(const LL, int>& p) const {
    40. // return p.first < p.second;
    41. // }
    42. //};
    43. //struct Node
    44. //{
    45. // int x,y,r;
    46. //}cir[maxn];
    47. vector<LL> cir;
    48. unordered_map<LL,int> mp;
    49. unordered_map<LL,int> vis;
    50. int n,m;
    51. void dfs_Trave(int x,int y,int r);
    52. void dfs(int x,int y,int r);
    53. int main()
    54. {
    55. // int a=123456789,b=123456;
    56. // int c=a&b;
    57. // cout << c << endl;
    58. // int a=123456789,b=45612;
    59. // cout << hash_val(a,b) << endl;
    60. scanf("%d%d",&n,&m);
    61. int x,y,r;
    62. for(int i=0;i<n;++i)
    63. {
    64. scanf("%d%d%d",&x,&y,&r);
    65. //cir[i]={x,y,r};
    66. LL temp=hash_val(x,y);
    67. //string temp=to_string(val);
    68. cir.push_back(temp);
    69. // mp[temp]=r;
    70. // vis[temp]=0;
    71. auto it=mp.find(temp);
    72. if(it==mp.end())
    73. {
    74. vis[temp]=0;
    75. mp[temp]=r;
    76. }
    77. else
    78. {
    79. if(r>it->second)
    80. mp[temp]=r;
    81. }
    82. }
    83. // cout << "调试:\n";
    84. // for(auto val:mp)
    85. // cout << val.first << ' ' << val.second << endl;
    86. // cout << "\ntiaoshi\n";
    87. // for(auto a:vis)
    88. // cout << a.first << ' ' << a.second << endl;
    89. int res=0;
    90. for(int i=0;i<m;++i)
    91. {
    92. scanf("%d%d%d",&x,&y,&r);
    93. dfs_Trave(x,y,r);
    94. }
    95. // cout << "\ntiaoshi2:\n";
    96. // for(auto a:vis)
    97. // cout << a.first << ' ' << a.second << endl;
    98. for(int i=0;i<n;++i)
    99. {
    100. auto temp=cir[i];
    101. if(vis[temp]!=0)
    102. ++res;
    103. }
    104. printf("%d\n",res);
    105. return 0;
    106. }
    107. void dfs(int x,int y,int r)
    108. {
    109. LL val=hash_val(x,y);
    110. // int x=index.first.first,y=index.first.second,r=index.second;
    111. vis[val]=1;
    112. for(int l=x-r;l<=x+r;++l)
    113. for(int s=y+r;s>=y-r;--s)
    114. {
    115. if(squ(r) >= squ(l-x) + squ(s-y))
    116. {
    117. auto temp=hash_val(l,s);
    118. auto it=mp.find(temp);
    119. if(it!=mp.end())
    120. {
    121. if(vis[temp]==0)
    122. dfs(l,s,it->second);
    123. }
    124. }
    125. }
    126. }
    127. void dfs_Trave(int x,int y,int r)
    128. {
    129. for(int l=x-r;l<=x+r;++l)
    130. for(int s=y+r;s>=y-r;--s)
    131. {
    132. if(squ(r) >= squ(l-x) + squ(s-y))
    133. {
    134. LL temp=hash_val(l,s);
    135. //string temp=to_string(val);
    136. auto it=mp.find(temp);
    137. if(it!=mp.end())
    138. {
    139. if(vis[temp]==0)
    140. dfs(l,s,it->second);
    141. }
    142. }
    143. }
    144. }

    第九个,

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

    */

    1. /**
    2. 将坐标转换为string,存在unordered_map中
    3. 在acwing只能过4/11;
    4. */
    5. #include <iostream>
    6. #include <cstdio>
    7. #include <cmath>
    8. #include <vector>
    9. #include <string>
    10. #include <unordered_map>
    11. using namespace std;
    12. typedef long long LL;
    13. LL squ(int x)
    14. {
    15. return (LL) x*x;
    16. }
    17. const int maxn=50010,inf=1e9;
    18. LL hash_val(int x)
    19. {
    20. return x*(inf+1ll);
    21. }
    22. /*
    23. struct cmp
    24. {
    25. bool operator()(pair<int,int> const &p) const
    26. {
    27. return p.first<p.second;
    28. }
    29. };
    30. */
    31. //struct cmp
    32. //{
    33. // std::size_t operator()(const std::pair<int, int>& p) const {
    34. // return p.first ^ p.second;
    35. // }
    36. //};
    37. //struct cmp
    38. //{
    39. // int operator()(const LL, int>& p) const {
    40. // return p.first < p.second;
    41. // }
    42. //};
    43. //struct Node
    44. //{
    45. // int x,y,r;
    46. //}cir[maxn];
    47. vector<string> cir;
    48. unordered_map<string,int> mp;
    49. unordered_map<string,int> vis;
    50. int n,m;
    51. void dfs_Trave(int x,int y,int r);
    52. void dfs(int x,int y,int r);
    53. int main()
    54. {
    55. // int a=123456789,b=123456;
    56. // int c=a&b;
    57. // cout << c << endl;
    58. // int a=123456789,b=45612;
    59. // cout << hash_val(a,b) << endl;
    60. // int a=122,b=456;
    61. // string s=to_string(a) +' ' +to_string(b);
    62. // cout << s << endl;
    63. scanf("%d%d",&n,&m);
    64. int x,y,r;
    65. for(int i=0;i<n;++i)
    66. {
    67. scanf("%d%d%d",&x,&y,&r);
    68. //cir[i]={x,y,r};
    69. LL val=hash_val(x);
    70. string temp=to_string(val)+' ' +to_string(y);
    71. cir.push_back(temp);
    72. // mp[temp]=r;
    73. // vis[temp]=0;
    74. auto it=mp.find(temp);
    75. if(it==mp.end())
    76. {
    77. vis[temp]=0;
    78. mp[temp]=r;
    79. }
    80. else
    81. {
    82. if(r>it->second)
    83. mp[temp]=r;
    84. }
    85. }
    86. // cout << "调试:\n";
    87. // for(auto val:mp)
    88. // cout << val.first << ' ' << val.second << endl;
    89. // cout << "\ntiaoshi\n";
    90. // for(auto a:vis)
    91. // cout << a.first << ' ' << a.second << endl;
    92. int res=0;
    93. for(int i=0;i<m;++i)
    94. {
    95. scanf("%d%d%d",&x,&y,&r);
    96. dfs_Trave(x,y,r);
    97. }
    98. // cout << "\ntiaoshi2:\n";
    99. // for(auto a:vis)
    100. // cout << a.first << ' ' << a.second << endl;
    101. for(int i=0;i<n;++i)
    102. {
    103. auto temp=cir[i];
    104. if(vis[temp]!=0)
    105. ++res;
    106. }
    107. printf("%d\n",res);
    108. return 0;
    109. }
    110. void dfs(int x,int y,int r)
    111. {
    112. LL val=hash_val(x);
    113. string temp=to_string(val) +' ' + to_string(y);
    114. // int x=index.first.first,y=index.first.second,r=index.second;
    115. vis[temp]=1;
    116. for(int l=x-r;l<=x+r;++l)
    117. for(int s=y+r;s>=y-r;--s)
    118. {
    119. if(squ(r) >= squ(l-x) + squ(s-y))
    120. {
    121. LL val=hash_val(l);
    122. string temp=to_string(val)+' ' +to_string(s);
    123. auto it=mp.find(temp);
    124. if(it!=mp.end())
    125. {
    126. if(vis[temp]==0)
    127. dfs(l,s,it->second);
    128. }
    129. }
    130. }
    131. }
    132. void dfs_Trave(int x,int y,int r)
    133. {
    134. for(int l=x-r;l<=x+r;++l)
    135. for(int s=y+r;s>=y-r;--s)
    136. {
    137. if(squ(r) >= squ(l-x) + squ(s-y))
    138. {
    139. LL val=hash_val(l);
    140. string temp=to_string(val)+' ' + to_string(s);
    141. auto it=mp.find(temp);
    142. if(it!=mp.end())
    143. {
    144. if(vis[temp]==0)
    145. dfs(l,s,it->second);
    146. }
    147. }
    148. }
    149. }

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

    */

    1. /**
    2. dfs实现图的遍历
    3. 手写hash表:把每个点唯一表示一个值,然后存到一个数组中,由于最大值为1e9,
    4. 所以可以把x坐标乘以一个(1e9+1)+y的坐标表示一个long long 值,也不会溢出,
    5. 即表示为一个两位的进制数,不过这个进制是1e9+1;
    6. 能AC;
    7. */
    8. #include <iostream>
    9. #include <cstdio>
    10. #include <vector>
    11. #include <cmath>
    12. #include <cstring>
    13. using namespace std;
    14. const int maxn=1e9,mod=7000003;
    15. int test=999997; //测试数是否为素数
    16. typedef long long LL;
    17. struct Node
    18. {
    19. int x,y,r;
    20. }cir[mod];
    21. LL hs[mod]={0};
    22. int id[mod]={0},vis[mod]={0};
    23. int m,n;
    24. void dfs(int x,int y,int r);
    25. void dfs_Trave(int x,int y,int r);
    26. LL hash_val(int x,int y) //将二维坐标转换为一个hash值
    27. {
    28. return (maxn+1ll)*x+y;
    29. }
    30. int hash_key(int x,int y)
    31. {
    32. LL val=hash_val(x,y);
    33. int k=1,flag=-1;
    34. int key=(val%mod+mod)%mod;
    35. while(hs[key]!=-1&&hs[key]!=val) //此处需要hs[key]!=key,因为后面需要查找用到二维坐标,
    36. { //返回一个key值
    37. key+=k*k*flag; //由于一个坐标最开始对应的key值也许被其他坐标占用了,这就需要查找
    38. ++k; //一个没被用到的值,但考虑到一个值一个值的加,元素容易扎堆都被使用了,
    39. flag*=-1; //于是我们就用平方探查法来查找
    40. key=(key%mod+mod)%mod; //防止出现负值
    41. }
    42. return key;
    43. }
    44. LL squ(int x)
    45. {
    46. return (LL) x*x;
    47. }
    48. void is_primer(int n)
    49. {
    50. for(int i=2;i<=sqrt(n);++i)
    51. if(n%i==0)
    52. {
    53. cout << " not is primer ;\n";
    54. return;
    55. }
    56. cout << "is primer\n";
    57. return;
    58. }
    59. int main()
    60. {
    61. is_primer(test);
    62. memset(hs,-1,sizeof(hs));
    63. scanf("%d%d",&n,&m);
    64. int x,y,r;
    65. for(int i=0;i<n;++i)
    66. {
    67. scanf("%d%d%d",&x,&y,&r);
    68. cir[i]={x,y,r};
    69. auto key=hash_key(x,y);
    70. if(hs[key]==-1) //这一个if语句需不需要都行
    71. hs[key]=hash_val(x,y);
    72. if(!id[key]||r>id[key]) //如果id[key]第一次被使用,或者此点的半径比之前的大,
    73. id[key]=r; //那么更新这个点的半径
    74. }
    75. int res=0;
    76. for(int i=0;i<m;++i)
    77. {
    78. scanf("%d%d%d",&x,&y,&r);
    79. dfs_Trave(x,y,r);
    80. }
    81. for(int i=0;i<n;++i)
    82. {
    83. auto key=hash_key(cir[i].x,cir[i].y);
    84. if(vis[key]!=0)
    85. ++res;
    86. }
    87. printf("%d\n",res);
    88. return 0;
    89. }
    90. void dfs(int x,int y,int r)
    91. {
    92. int key=hash_key(x,y);
    93. vis[key]=1;
    94. for(int l=x-r;l<=x+r;++l) //遍历(x,y)周围可以炸到的所有点
    95. for(int s=y+r;s>=y-r;--s)
    96. {
    97. if(squ(r) >= squ(l-x) + squ(s-y))
    98. {
    99. int key=hash_key(l,s);
    100. if(hs[key]!=-1) //如果这个点处有炸弹
    101. {
    102. if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
    103. dfs(l,s,id[key]);
    104. }
    105. }
    106. }
    107. }
    108. void dfs_Trave(int x,int y,int r)
    109. {
    110. for(int l=x-r;l<=x+r;++l) //遍历(x,y)周围可以炸到的所有点
    111. for(int s=y+r;s>=y-r;--s)
    112. {
    113. if(squ(r) >= squ(l-x) + squ(s-y))
    114. {
    115. int key=hash_key(l,s);
    116. if(hs[key]!=-1) //如果这个点处有炸弹
    117. {
    118. if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
    119. dfs(l,s,id[key]);
    120. }
    121. }
    122. }
    123. }

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

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

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

    1. /**
    2. 用BFS实现图的遍历,
    3. 手写hash表:把每个点唯一表示一个值,然后存到一个数组中,由于最大值为1e9,
    4. 所以可以把x坐标乘以一个(1e9+1)+y的坐标表示一个long long 值,也不会溢出,
    5. 即表示为一个两位的进制数,不过这个进制是1e9+1
    6. true coding,能AC
    7. */
    8. /**
    9. #include <iostream>
    10. #include <cstdio>
    11. #include <vector>
    12. #include <queue>
    13. #include <cmath>
    14. #include <cstring>
    15. using namespace std;
    16. const int maxn=1e9,mod=700001,ne=50010;
    17. int test=700001; //测试数是否为素数
    18. typedef long long LL;
    19. struct Node
    20. {
    21. int x,y,r;
    22. }cir[ne];
    23. LL hs[mod]={0};
    24. int id[mod]={0},vis[mod]={0};
    25. int m,n;
    26. void bfs(Node zd);
    27. void bfs_Trave(int x,int y,int r);
    28. LL hash_val(int x,int y) //将二维坐标转换为一个hash值
    29. {
    30. return (maxn+1ll)*x+y;
    31. }
    32. int hash_key(int x,int y)
    33. {
    34. LL val=hash_val(x,y);
    35. int k=1,flag=-1;
    36. int key=(val%mod+mod)%mod;
    37. while(hs[key]!=-1&&hs[key]!=val) //此处需要hs[key]!=key,因为后面需要查找用到二维坐标,
    38. { //返回一个key值
    39. key+=k*k*flag; //由于一个坐标最开始对应的key值也许被其他坐标占用了,这就需要查找
    40. ++k; //一个没被用到的值,但考虑到一个值一个值的加,元素容易扎堆都被使用了,
    41. flag*=-1; //于是我们就用平方探查法来查找
    42. key=(key%mod+mod)%mod; //防止出现负值
    43. }
    44. return key;
    45. }
    46. LL squ(int x)
    47. {
    48. return (LL) x*x;
    49. }
    50. void is_primer(int n)
    51. {
    52. for(int i=2;i<=sqrt(n);++i)
    53. if(n%i==0)
    54. {
    55. cout << " not is primer ;\n";
    56. return;
    57. }
    58. cout << "is primer\n";
    59. return;
    60. }
    61. int main()
    62. {
    63. //is_primer(test);
    64. memset(hs,-1,sizeof(hs));
    65. scanf("%d%d",&n,&m);
    66. int x,y,r;
    67. for(int i=0;i<n;++i)
    68. {
    69. scanf("%d%d%d",&x,&y,&r);
    70. cir[i]={x,y,r};
    71. auto key=hash_key(x,y);
    72. if(hs[key]==-1) //这一个if语句需不需要都行
    73. hs[key]=hash_val(x,y);
    74. if(!id[key]||r>id[key]) //如果id[key]第一次被使用,或者此点的半径比之前的大,
    75. id[key]=r; //那么更新这个点的半径
    76. }
    77. int res=0;
    78. for(int i=0;i<m;++i)
    79. {
    80. scanf("%d%d%d",&x,&y,&r);
    81. bfs_Trave(x,y,r);
    82. }
    83. for(int i=0;i<n;++i)
    84. {
    85. auto key=hash_key(cir[i].x,cir[i].y);
    86. if(vis[key]!=0)
    87. ++res;
    88. }
    89. printf("%d\n",res);
    90. return 0;
    91. }
    92. void bfs(Node zd)
    93. {
    94. queue<Node> q;
    95. q.push(zd);
    96. while(!q.empty())
    97. {
    98. Node temp=q.front();
    99. int x=temp.x,y=temp.y,r=temp.r;
    100. q.pop();
    101. int key=hash_key(x,y);
    102. // vis[key]=1;
    103. for(int l=x-r;l<=x+r;++l) //遍历(xy)周围可以炸到的所有点
    104. for(int s=y+r;s>=y-r;--s)
    105. {
    106. if(squ(r) >= squ(l-x) + squ(s-y))
    107. {
    108. int key=hash_key(l,s);
    109. if(hs[key]!=-1) //如果这个点处有炸弹
    110. {
    111. if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
    112. {
    113. q.push({l,s,id[key]});
    114. vis[key]=1; //值得一提的是,vis[key]应当在进入bfs的队列便更新这个值已被访问
    115. } //,否则取出一个坐标的时候再更新,会导致一个点多次入队
    116. } //,浪费许多时间,acwing上最后一组数据超时,问题便出现在这儿
    117. }
    118. }
    119. }
    120. }
    121. void bfs_Trave(int x,int y,int r)
    122. {
    123. for(int l=x-r;l<=x+r;++l) //遍历(xy)周围可以炸到的所有点
    124. for(int s=y+r;s>=y-r;--s)
    125. {
    126. if(squ(r) >= squ(l-x) + squ(s-y))
    127. {
    128. int key=hash_key(l,s);
    129. if(hs[key]!=-1) //如果这个点处有炸弹
    130. {
    131. if(vis[key]==0) //如果这个点处的炸弹没被拆除掉
    132. {
    133. vis[key]=1;
    134. bfs({l,s,id[key]});
    135. }
    136. }
    137. }
    138. }
    139. }
    140. */

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

    1. /**借鉴正确代码
    2. */
    3. /**
    4. #include <iostream>
    5. #include <cstdio>
    6. #include <vector>
    7. #include <queue>
    8. #include <cmath>
    9. #include <cstring>
    10. using namespace std;
    11. const int maxn=1e9,mod=1e6 + 7,ne=50010;
    12. int test=700001; //测试数是否为素数
    13. typedef long long LL;
    14. struct Node
    15. {
    16. int x,y,r;
    17. }cir[ne];
    18. LL hs[mod]={0};
    19. int id[mod]={0}; //id存储的是坐标在数组cir中对应的下标
    20. bool vis[ne]={0};
    21. int m,n;
    22. void bfs(int index);
    23. void bfs_Trave(int x,int y,int r);
    24. LL hash_val(int x,int y) //将二维坐标转换为一个hash值
    25. {
    26. return (maxn+1ll)*x+y;
    27. }
    28. int hash_key(int x,int y)
    29. {
    30. LL val=hash_val(x,y);
    31. int key=(val%mod+mod)%mod;
    32. while(hs[key]!=-1&&hs[key]!=val) //此处需要hs[key]!=key,因为后面需要查找用到二维坐标,
    33. { //返回一个key值
    34. key++;
    35. if(key == mod) key = 0; //防止出现负值
    36. }
    37. return key;
    38. }
    39. LL squ(int x)
    40. {
    41. return (LL) x*x;
    42. }
    43. int main()
    44. {
    45. memset(hs,-1,sizeof(hs));
    46. scanf("%d%d",&n,&m);
    47. int x,y,r;
    48. for(int i=1;i<=n;++i)
    49. {
    50. scanf("%d%d%d",&x,&y,&r);
    51. cir[i]={x,y,r};
    52. auto key=hash_key(x,y);
    53. if(hs[key]==-1) //这一个if语句需不需要都行
    54. hs[key]=hash_val(x,y);
    55. if(!id[key]||r>cir[id[key]].r) //如果id[key]第一次被使用,或者此点的半径比之前的大,
    56. id[key]=i; //那么更新这个点的坐标下标
    57. }
    58. int res=0;
    59. for(int i=0;i<m;++i)
    60. {
    61. scanf("%d%d%d",&x,&y,&r);
    62. bfs_Trave(x,y,r);
    63. }
    64. for(int i=1;i<=n;++i)
    65. {
    66. auto key=hash_key(cir[i].x,cir[i].y);
    67. int pos=id[key];
    68. if(pos&&vis[pos])
    69. ++res;
    70. }
    71. printf("%d\n",res);
    72. return 0;
    73. }
    74. void bfs(int index)
    75. {
    76. queue<int> q;
    77. q.push(index);
    78. vis[index]=1;
    79. while(!q.empty())
    80. {
    81. int temp=q.front();
    82. int x=cir[temp].x,y=cir[temp].y,r=cir[temp].r;
    83. q.pop();
    84. //int key=hash_key(x,y);
    85. //vis[temp]=1; //在这儿将temp号的值赋为1便是错的,不知道原因
    86. for(int l=x-r;l<=x+r;++l) //遍历(xy)周围可以炸到的所有点
    87. for(int s=y+r;s>=y-r;--s)
    88. {
    89. if(squ(r) >= squ(l-x) + squ(s-y))
    90. {
    91. int key=hash_key(l,s);
    92. if(id[key]&&!vis[id[key]]) //如果这个点处有炸弹
    93. {
    94. int pos=id[key];//如果这个点处的炸弹没被拆除掉
    95. q.push(pos);
    96. vis[pos]=1;
    97. }
    98. }
    99. }
    100. }
    101. }
    102. void bfs_Trave(int x,int y,int r)
    103. {
    104. for(int l=x-r;l<=x+r;++l) //遍历(xy)周围可以炸到的所有点
    105. for(int s=y+r;s>=y-r;--s)
    106. {
    107. if(squ(r) >= squ(l-x) + squ(s-y))
    108. {
    109. int key=hash_key(l,s);
    110. if(id[key]&&!vis[id[key]]) //如果这个点处有炸弹
    111. { //如果这个点处的炸弹没被拆除掉
    112. bfs(id[key]);
    113. }
    114. }
    115. }
    116. }

  • 相关阅读:
    【数据结构】栈
    计算机网络-第六章 应用层(1)
    【附源码】Python计算机毕业设计芮城县十全十美火锅店点餐系统
    java八股文面试[设计模式]——结构型模式
    python的jira库的调用简单记录
    分享一份 .NET Core 简单的自带日志系统配置,平时做一些测试或个人代码研究,用它就可以了
    计算机操作系统
    14Maven与Tomcat面试题
    linux下mv命令移动目录的二种情况
    Java 入门笔记
  • 原文地址:https://blog.csdn.net/qq_51825761/article/details/125476155