当前位置:   article > 正文

「NOIP2017」 奶酪 - 并查集_java现有一块大奶酪

java现有一块大奶酪

题目大意

在一个三维空间内有一块长方体奶酪,下表面z=0,高度为h,长宽无限,其中有一些可以通过的空洞,如果两个洞相交或相切,就可以从一个空洞跑到另一个空洞。给定h和每个空洞的球心坐标和半径,问能否从下表面跑到上表面。

分析

首先要明白对于两个球体A,B如果AB的球心距离小于等于两半径和,两球相切或相交。然后,维护一个并查集,建立一个超级起点z=0和超级终点z=h,如果两个球连通,就将它们并起来,如果与下表面相切,就与超级起点并起来,与上表面相切,就与超级终点并起来。最后查看起点与终点是否在同一个并查集内即可。

代码

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cmath>
  4. #define ll long long
  5. using namespace std;
  6. ll T,n;
  7. double h,r,low,high;
  8. int f[1010];
  9. struct ball {
  10. double x,y,z;
  11. }s[1010];
  12. double dist(ball a,ball b) {
  13. double x=a.x-b.x,y=a.y-b.y,z=a.z-b.z;
  14. return sqrt(x*x+y*y+z*z);
  15. }
  16. int getf(int x) {
  17. if (f[x]==x) return x;
  18. return f[x]=getf(f[x]);
  19. }
  20. void Union(int x,int y) {
  21. x=getf(x);
  22. y=getf(y);
  23. if (x!=y) f[y]=f[x];
  24. }
  25. int main() {
  26. scanf("%lld",&T);
  27. while (T--) {
  28. scanf("%lld%lf%lf",&n,&h,&r);
  29. low=h;high=0;
  30. for (int i = 1;i <= n;i++) {
  31. scanf("%lf%lf%lf",&s[i].x,&s[i].y,&s[i].z);
  32. low=min(low,s[i].z);
  33. high=max(high,s[i].z);
  34. }
  35. if (low-r>0||high+r<h) {
  36. printf("No\n");
  37. continue;
  38. }
  39. for (int i = 0;i <= n+1;i++) f[i]=i;
  40. for (int i = 1;i <= n;i++) {
  41. if (s[i].z-r<=0) Union(0,i);
  42. if (s[i].z+r>=h) Union(i,n+1);
  43. }
  44. for (int i = 1;i < n;i++)
  45. for (int j = i+1;j <= n;j++)
  46. if (dist(s[i],s[j])<=2*r)
  47. Union(i,j);
  48. if (getf(0)==getf(n+1)) printf("Yes\n");
  49. else printf("No\n");
  50. }
  51. return 0;
  52. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/792370
推荐阅读
相关标签
  

闽ICP备14008679号