11253F-Girlfriend

难得过道数学题,写发sol纪念一波。

题意

给出
要求计算限制条件下两点的合法空间的相交部分体积

思路

0.样例

一开始以为是简单的几何题,拿着样例比划了两下,觉得可能要用二重积分,放弃

1.暴力

数据范围因为是三维空间,暴力枚举所有点肯定是不行的,何况输出还是浮点数,后面想了想优化的方法,即用二分计算边界值,减小枚举范围,又考虑到极端数据的存在,放弃

2.只有用数学才能打败数学!

多次尝试无果,于是静下心来写出式子进行推导
为例
根据限制条件先写出关系式:
化简得:
因为的系数相同,若不等式的改为则是球面的一般方程,即不等式表示全体离球心距离小于等于半径的点(简单说就是球面上及内部的所有点)
此时只需要通过一般方程各项系数即可算出的球心坐标和半径,同理可得的球心坐标和半径。
最后,只需判断两个球是否相交,若相交则计算出相交部分的体积(两个球缺),寄!
第一次写题解,可能有的地方没写好,欢迎指正。

利用球面一般方程的系数计算球心坐标和半径

写出一般方程:
化作标准方程:
易得球心坐标,半径

代码

#include <bits/stdc++.h>
#define INF 99999999
#define LINF LLONG_MAX 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAX_N=1;
const double pi = acos(-1);

int T;
double x[5],y[5],z[5];
double k1,k2;

void solve(double x1,double y1,double z1,double r1,double x2,double y2,double z2,double r2){
    double ans=0;
    //球心距离 
    double dis=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
    //相离或相切 
    if(dis>=r1+r2){
        ans=0;
    }
    //内含或内切 
    else if (dis+r1<=r2){
        ans=(4.00/3.00)*pi*r1*r1*r1;
    }
    else if(dis+r2<=r1){
        ans=(4.00/3.00)*pi*r2*r2*r2;
    }
    //相交 
    else{
        //计算cos1 
        double cal=(r1*r1+dis*dis-r2*r2)/(2.00*dis*r1);
        //计算h1 
        double h=r1*(1-cal);
    	//计算球缺1体积 
        ans+=(1.00/3.00)*pi*(3.00*r1-h)*h*h;
        //计算cos2 
        cal=(r2*r2+dis*dis-r1*r1)/(2.00*dis*r2);
        //计算h2 
        h=r2*(1.00-cal);
        //计算球缺2体积 
        ans+=(1.00/3.00)*pi*(3.00*r2-h)*h*h;
    }
    printf("%.3f\n",ans);
}

int main(){
	cin>>T;
	while(T--){
		for(int i=0;i<4;i++)
			cin>>x[i]>>y[i]>>z[i];
		cin>>k1>>k2;
		//计算球1的球心坐标和半径 
		double xishu1=k1*k1-1;
		double c1x,c1y,c1z,c1r,t;
		c1x=(k1*k1*x[1]-x[0])/xishu1;
		c1y=(k1*k1*y[1]-y[0])/xishu1;
		c1z=(k1*k1*z[1]-z[0])/xishu1;
		t=k1*k1*((x[1]*x[1])+(y[1]*y[1])+(z[1]*z[1]))-x[0]*x[0]-y[0]*y[0]-z[0]*z[0];
		t/=xishu1;
		c1r=sqrt(c1x*c1x+c1y*c1y+c1z*c1z-t);
		//计算球2的球心坐标和半径 
		double xishu2=k2*k2-1;
		double c2x,c2y,c2z,c2r;
		c2x=(k2*k2*x[3]-x[2])/xishu2;
		c2y=(k2*k2*y[3]-y[2])/xishu2;
		c2z=(k2*k2*z[3]-z[2])/xishu2;
		t=k2*k2*((x[3]*x[3])+(y[3]*y[3])+(z[3]*z[3]))-x[2]*x[2]-y[2]*y[2]-z[2]*z[2];
		t/=xishu2;
		c2r=sqrt(c2x*c2x+c2y*c2y+c2z*c2z-t);
		//计算两个球相交部分体积 
		solve(c1x,c1y,c1z,c1r,c2x,c2y,c2z,c2r);
	}
	return 0;
}

/*
样例
1
1 0 0
3 0 0
2 0 0
4 0 0
3 3
输出
0.262
*/