链接:https://ac.nowcoder.com/acm/contest/373/E
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld

题目描述

某天lililalala正在玩一种奇妙的吃鸡游戏--因为在这个游戏里会同时有两个圆形安全区(他们可能相交)。

lililalala觉得求圆的面积并太简单了,所以想把这个问题升级一下。

现在在三维空间里有 2 个球形安全区,分别用四元组  <x1,y1,z1,r1>和 <x2,y2,z2,r2> 表示,其中  r1、r2 表示球半径, (x1,y1,z1)和 (x2,y2,z2) 表示球心

lililalala想知道安全区的总体积是多少?即求这两个球的体积并。

 

 

输入描述:


 

输入有两行。

第一行四个实数 x1,y1,z1,r1 --第一个球的球心坐标和半径。

第二行四个实数 x2,y2,z2,r2--第二个球的球心坐标和半径。

保证所有输入的坐标和半径的范围都在 [−100,100] 内。半径为非负数。

输出描述:

输出一行一个实数--表示两个球的体积并,你的答案被认为正确,当且仅当绝对误差不超过 10−6 10−6。

示例1

输入

复制

0 0 0 1
2 0 0 1

输出

复制

8.3775804

示例2

输入

复制

0 0 0 1
0 0 0 0.5

输出

复制

4.1887902

题意:求球的体积并~

题解:

球的体积:4.0/3πr^3,球的表面积:4πr^2

球冠面积S=2πrh(此处为扩展,此题用不到)      球缺的体积公式为V=πh^2(r−h/3)        h为球冠高  ,r为球半径,此题关键是求h~~

两球心距离=l    半径分别为r1 , r2     两球相交的截面为平面,相交线为圆,半径为r3     截面到球心的距离分别为l1 ,l2   l1+l2=l;

则很容易知道:

r1^2=r3^2+l1^2; 
r2^2=r3^2+l2^2;

因为r1,r3,l1 和 r2,r3,l2分别形成两个直角三角形,斜边为r1和r2;
用上面第一个式子减第二个式子得到:

r1^2−r2^2=l1^2−l2^2
r1^2−r2^=(l1+l2)(l1−l2)

因为 l1+l2=l; 所以l2=l-l1

则:r1^2−r2^2=(2l1−l)l 
l1=[(r1^2−r2^2)/l+l]/2
l2=l−l1
两个球冠高:h1=r1−l1  h2=r2−l2

这是在两球相交的情况下的推导~~其他情况体积并好求~~~

上代码:

#include <iostream>
#include <cmath>
using namespace std;
const double pi = acos(-1.0);
int main(){
    double x1,y1,z1,r1;
    cin >> x1 >> y1 >> z1 >> r1;
    double x2,y2,z2,r2;
    cin >> x2 >> y2 >> z2 >> r2;
    double rr1=r1+r2;//半径和
    double rr2=fabs(r1-r2);//半径差
    double l=sqrt(pow(x1-x2,2)+pow(y1-y2,2)+pow(z1-z2,2));//球心距
    if(rr1<=l) printf("%.7f\n",4.0/3*pi*r1*r1*r1+4.0/3*pi*r2*r2*r2);//两球相离和外切,总体积
    else if(rr2>=l){//两球内含和内切,j较大的那个球的体积
        double maxx=max(r1,r2);
        printf("%.7f\n",4.0/3*pi*maxx*maxx*maxx);
    }
    else {//两球相交
        double l1,l2,h1,h2,v,v1,v2;
        l1=((r1*r1-r2*r2)/l+l)/2;
        l2=l-l1;
        h1=r1-l1;//求出h1
        h2=r2-l2;//求出h2
        v1=pi*h1*h1*(r1-h1/3);//相交部分的体积1
        v2=pi*h2*h2*(r2-h2/3);////相交部分的体积2
        v=4.0/3*pi*r1*r1*r1+4.0/3*pi*r2*r2*r2;//总体积
        printf("%.7f\n",v-v1-v2);
    }
    return 0;
}