计算几何-求球冠体积

球冠的体积

今天来谈谈计算几何,怎么就球冠的体积,对于一个高为 h h 的球冠,如图所示:
在这里插入图片描述
那么显然要求这个球冠的体积就需要积分,考虑截面法,这个球冠的每个横截面都是一个圆,这个圆的半径假设为 r r , 那么可以知道积分式为:
V = π 0 h ( r 2 ( r x ) 2 ) d x = π [ r x 2 1 3 x 3 ] 0 h = π h 2 ( r 1 3 h ) V=\pi\int_{0}^{h}(r^2-(r-x)^2)dx=\pi[r\cdot x^2-\frac{1}{3}\cdot x^3 ]_{0}^{h}=\pi \cdot h^2(r-\frac{1}{3} \cdot h)

有了这个之后我们就来看题:
https://ac.nowcoder.com/acm/contest/373/E
这个题目是要求两个球的体积并,考虑两种情况,当两个球不想交时,此时答案就是两个球的体积和。当两个球想交时也就是 d < r 1 + r 2 d<r_1+r_2 , 这时球的体积并为两个球的体积再分别扣除两个球冠的体积,对于求球冠的体积,我们参考如下图(画得有点low哈):
在这里插入图片描述
我们可以推导出一个关系就是 R 1 2 x 2 = R 2 2 ( d x ) 2 R_1^2-x^2=R_2^2-(d-x)^2 , 从而推 x = ( R 1 2 + R 2 2 + d 2 ) / 2 d x=(R_1^2+ -R_2^2+d^2)/2d 然后可以得出
h 1 = R 1 x h_1=R_1-x h 2 = R 2 ( d x ) h2=R_2-(d-x)
然后再分别讨论两个圆相交和外离以及内含的关系就行了.
{ R 1 + R 2 d R 1 R 2 d R 1 R 2 d R 1 + R 2 \left\{\begin{matrix}R_1+R_2 \leq d \\ R_1-R_2 \geq d \\ R_1-R_2 \leq d \leq R_1+R_2 \end{matrix}\right.

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;
}

新的开始,每天都要快乐哈!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_39393640/article/details/88073954