链接: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;
}