Cosmic Cleaner
题意:给你很多球的中心坐标和半径,还有一个大球的中心坐标和半径,让你求大球可以占据其他球的体积和
思路:球缺问题,先判断其他球和大球的关系,如果相离则不用考虑,即两中心点的距离大于两半径之和
如果在球内部,则两中心距离加上小球半径仍小于最大球的半径,那么相交体积就是小球的体积
如果相交,那么就是求球缺即可
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #define CLR(a,b) memset(a,b,sizeof(a)); 6 const int inf=0x3f3f3f3f; 7 #include<bits/stdc++.h> 8 using namespace std; 9 const double PI = acos(-1.0); 10 typedef unsigned long long ll; 11 const int maxn= 110; 12 typedef struct point { 13 double x,y,z; 14 point() { 15 } 16 point(double a, double b,double c) { 17 x = a; 18 y = b; 19 z = c; 20 } 21 point operator -(const point &b)const { //返回减去后的新点 22 return point(x - b.x, y - b.y,z-b.z); 23 } 24 point operator +(const point &b)const { //返回加上后的新点 25 return point(x + b.x, y + b.y,z+b.z); 26 } 27 //数乘计算 28 point operator *(const double &k)const { //返回相乘后的新点 29 return point(x * k, y * k,z*k); 30 } 31 point operator /(const double &k)const { //返回相除后的新点 32 return point(x / k, y / k,z/k); 33 } 34 double operator *(const point &b)const { //点乘 35 return x*b.x + y*b.y+z*b.z; 36 } 37 }point; 38 39 double dist(point p1, point p2) { //返回平面上两点距离 40 return sqrt((p1 - p2)*(p1 - p2)); 41 } 42 typedef struct sphere {//球 43 double r; 44 point centre; 45 }sphere; 46 sphere s,a[maxn]; 47 void SphereInterVS(sphere a, sphere b,double &v,double &s) { 48 double d = dist(a.centre, b.centre);//球心距 49 double t = (d*d + a.r*a.r - b.r*b.r) / (2.0 * d);// 50 double h = sqrt((a.r*a.r) - (t*t)) * 2;//h1=h2,球冠的高 51 double angle_a = 2 * acos((a.r*a.r + d*d - b.r*b.r) / (2.0 * a.r*d)); //余弦公式计算r1对应圆心角,弧度 52 double angle_b = 2 * acos((b.r*b.r + d*d - a.r*a.r) / (2.0 * b.r*d)); //余弦公式计算r2对应圆心角,弧度 53 double l1 = ((a.r*a.r - b.r*b.r) / d + d) / 2; 54 double l2 = d - l1; 55 double x1 = a.r - l1, x2 = b.r - l2;//分别为两个球缺的高度 56 double v1 = PI*x1*x1*(a.r - x1 / 3);//相交部分r1圆所对应的球缺部分体积 57 double v2 = PI*x2*x2*(b.r - x2 / 3);//相交部分r2圆所对应的球缺部分体积 58 v = v1 + v2;//相交部分体积 59 double s1 = PI*a.r*x1; //r1对应球冠表面积 60 double s2 = PI*a.r*x2; //r2对应球冠表面积 61 s = 4 * PI*(a.r*a.r + b.r*b.r) - s1 - s2;//剩余部分表面积 62 } 63 int t, n; 64 double x, y, z, r; 65 int cas = 1; 66 int main() 67 { 68 cin >> t; 69 while(t--) 70 { 71 cin >> n; 72 for(int i = 1; i <= n; i++) 73 { 74 scanf("%lf%lf%lf%lf",&x,&y,&z,&a[i].r); 75 a[i].centre = {x,y,z}; 76 } 77 scanf("%lf%lf%lf%lf",&x,&y,&z,&r); 78 s.r = r; 79 s.centre = {x,y,z}; 80 double ans = 0, v = 0; 81 for(int i = 1; i <= n; i++) 82 { 83 double ss, dis = dist(s.centre, a[i].centre); 84 85 if(dis >= s.r + a[i].r)continue; //两球相离,无相交部分 86 if(dis + min(s.r, a[i].r) <= max(s.r, a[i].r)) //在内部 87 { 88 ans += 4.0 / 3.0 * PI * min(s.r,a[i].r) * min(s.r,a[i].r) * min(s.r,a[i].r); 89 continue; 90 } 91 SphereInterVS(s, a[i], v, ss); //相交部分 92 ans += v; 93 } 94 printf("Case #%d: %.14f ",cas++,ans); 95 } 96 }