版权声明:欢迎神犇指教 https://blog.csdn.net/sdxtcqs/article/details/87016705
https://zhixincode.com/contest/9/problem/H
题意:在三维空间给定n个球体(圆心坐标和半径),给定以原点为圆心的球的半径,求该球与这n个球体有多少公共体积。
https://blog.csdn.net/enterprise_/article/details/81624174?tdsourcetag=s_pctim_aiomsg
↑↑↑参考该大神的博客可求出相交的两个球体的公共体积,然后特判一下包含和不相交的情况即可。
重点是球冠体积公式:
其中H是球冠的高,R是球冠的半径。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const double PI = acos(-1.0);
struct point {
double x,y,z;
point() {}
point(double a, double b,double c) {
x = a;
y = b;
z = c;
}
point operator -(const point &b)const { //返回减去后的新点
return point(x - b.x, y - b.y,z-b.z);
}
point operator +(const point &b)const { //返回加上后的新点
return point(x + b.x, y + b.y,z+b.z);
}
//数乘计算
point operator *(const double &k)const { //返回相乘后的新点
return point(x * k, y * k,z*k);
}
point operator /(const double &k)const { //返回相除后的新点
return point(x / k, y / k,z/k);
}
double operator *(const point &b)const { //点乘
return x*b.x + y*b.y+z*b.z;
}
};
double dist(point p1, point p2) { //返回平面上两点距离
return sqrt((p1 - p2)*(p1 - p2));
}
struct sphere {//球
double r;
point centre;
sphere() {}
sphere(point c,double rr) {
centre=c;
r=rr;
}
}arr[110];
double SphereInterV(sphere a, sphere b) {
double d = dist(a.centre, b.centre);//球心距
double l1 = ((a.r*a.r - b.r*b.r) / d + d) / 2.0;
double l2 = d - l1;
double x1 = a.r - l1, x2 = b.r - l2;//分别为两个球缺的高度
double v1 = PI*x1*x1*(a.r - x1 / 3.0);//相交部分r1圆所对应的球缺部分体积
double v2 = PI*x2*x2*(b.r - x2 / 3.0);//相交部分r2圆所对应的球缺部分体积
double v = v1 + v2;//相交部分体积
return v;
}
int n,T;
int main()
{
int t=1;
scanf("%d",&T);
while(T--)
{
memset(arr,0,sizeof(arr));
double xx,yy,zz,re,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&xx,&yy,&zz,&re);
point p(xx,yy,zz);
sphere sp(p,re);
arr[i]=sp;
}
scanf("%lf%lf%lf%lf",&xx,&yy,&zz,&re);
point pc(xx,yy,zz);
sphere sc(pc,re);
for(int i=1;i<=n;i++)
{
if(dist(sc.centre,arr[i].centre)+arr[i].r<=sc.r) ans+=4.0/3.0*PI*arr[i].r*arr[i].r*arr[i].r;
else if(dist(sc.centre,arr[i].centre)>=arr[i].r+sc.r) ans+=0;
else ans+=SphereInterV(sc,arr[i]);
}
printf("Case #%d: %.20lf\n",t,ans);
t++;
}
return 0;
}