球冠的体积
今天来谈谈计算几何,怎么就球冠的体积,对于一个高为
的球冠,如图所示:
那么显然要求这个球冠的体积就需要积分,考虑截面法,这个球冠的每个横截面都是一个圆,这个圆的半径假设为
, 那么可以知道积分式为:
有了这个之后我们就来看题:
https://ac.nowcoder.com/acm/contest/373/E
这个题目是要求两个球的体积并,考虑两种情况,当两个球不想交时,此时答案就是两个球的体积和。当两个球想交时也就是
, 这时球的体积并为两个球的体积再分别扣除两个球冠的体积,对于求球冠的体积,我们参考如下图(画得有点low哈):
我们可以推导出一个关系就是
, 从而推
然后可以得出
然后再分别讨论两个圆相交和外离以及内含的关系就行了.
AC代码
// 小学生一发的刷题之路
//
// Mannacher Algorithm
//
//
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <deque> //双向队列;
#include <cmath>
#include <set>
#include <stack>
#include <map>
#include <vector>
#include <cstdlib>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double PI=acos(-1.0);
const double eps=1e-8;
const int maxn=1e5+5;
const int maxm=1e3+5;
const ll mod=1e9+7;
const int INF=1e8;
template<class T>
inline void read(T &ret){ //快速输入模版;
ret=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ret=ret*10+c-'0';
c=getchar();
}
ret*=f;
}
template <class T>
inline void out(T ret){ //快速输出模版;
if(ret>9)
{
out(ret/10);
}
putchar(ret%10+'0');
}
struct node{
double x,y,z,r,V;
node(){};
}p[3];
double dist(node a,node b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
int main()
{
for(int i=1;i<=2;i++){
scanf("%lf %lf %lf %lf",&p[i].x,&p[i].y,&p[i].z,&p[i].r);
p[i].V=4*PI*pow(p[i].r,3)/3;
}
double d=dist(p[1],p[2]);
if(d-p[1].r-p[2].r>eps){ //相离;
printf("%0.8lf\n",p[1].V+p[2].V);
}else if(d<fabs(p[1].r-p[2].r)){ //包含;
printf("%0.8lf\n",max(p[1].V,p[2].V));
}else{
double h1=(p[1].r*p[1].r-p[2].r*p[2].r+d*d)/(2*d);
double h2=d-h1;
h1=p[1].r-h1;
h2=p[2].r-h2;
double v1=PI*h1*h1*(p[1].r-h1/3);
double v2=PI*h2*h2*(p[2].r-h2/3);
printf("%0.8lf\n",p[1].V+p[2].V-v1-v2);
}
return 0;
}
新的开始,每天都要快乐哈!