Wannafly Winter Camp 2019 Day2 H Cosmic Cleaner

时间:2019-02-11
本文章向大家介绍Wannafly Winter Camp 2019 Day2 H Cosmic Cleaner,主要包括Wannafly Winter Camp 2019 Day2 H Cosmic Cleaner使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

https://zhixincode.com/contest/9/problem/H
题意:在三维空间给定n个球体(圆心坐标和半径),给定以原点为圆心的球的半径,求该球与这n个球体有多少公共体积。
https://blog.csdn.net/enterprise_/article/details/81624174?tdsourcetag=s_pctim_aiomsg
↑↑↑参考该大神的博客可求出相交的两个球体的公共体积,然后特判一下包含和不相交的情况即可。
重点是球冠体积公式:V=πH2(RH3)V=\pi H^2(R-\frac{H}{3})
其中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;
}