题意:给A,B,C,D四点,k1,k2两个数,求满足∣AP1∣≥k1∣BP1∣,∣CP2∣≥k2∣DP2∣条件的重叠区域
emmm,推公式,要用数学打败数学
公式1:为什么是球?
我们以第一个式子为例,假设
化简得:
因为x²,y²,z²系数相同,满足球的标准方程,所以可知所求即为两个球相交的部分;
公式2:两个球相交的体积
1.两个球不相交:d>=R+r
2.小球包含在大球内:d<=R-r
3.两球相交:R-r<d<R+r
接下来就是代码实现:
#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
int t;
int x[5], y[5], z[5];
double a[3], b[3], c[3], d[3];
int k[3];
double r[3];
double radius(double a, double b, double c, double d)
{
return sqrt(a * a + b * b + c * c - d);
}
int main()
{
cin >> t;
while (t--)
{
for (int i = 0; i < 4; i++)
{
cin >> x[i] >> y[i] >> z[i];
}
cin >> k[0] >> k[1];
for (int i = 0; i < 4; i += 2)
{
int j = i >> 1;
int kk = k[j] * k[j];
a[j] =(kk * x[i + 1] - x[i])/double(1-kk);
b[j] = (kk* y[i + 1] - y[i]) / double(1 - kk);
c[j] =(kk * z[i + 1] - z[i]) / double(1 - kk);
d[j] = -x[i] * x[i]/ double( kk-1) - y[i] * y[i]/ double( kk-1)- z[i] * z[i]/ double( kk-1)+ kk/ double( kk-1) * (x[i + 1] * x[i + 1] + y[i + 1] * y[i + 1] +z[i + 1] * z[i + 1]);
//这里要除一下,不然会爆ll,然后就错了!//cout << d[j] << endl;
r[j] = radius(a[j], b[j], c[j] , d[j]);
}
double dis = sqrt(double((a[1] - a[0]) * (a[1] - a[0]) + (b[1] - b[0]) * (b[1] - b[0]) + (c[1] - c[0]) * (c[1] - c[0])));
//cout << d << endl;
double v=0;
if (dis >= r[0] + r[1])
{
printf("0\n");
}
else if (dis <= abs(r[1] - r[0]))
{
double R = min(r[1], r[0]);
v = 4 * R * R * R * PI / 3;
printf("%.3lf\n", v);
}
else
{
//cout << d << endl;
for (int i = 0; i < 2; i++)
{
double cs = (r[i] * r[i] + dis * dis - r[1 - i] * r[1 - i]) / (2.0 * dis*r[i]);
double h = r[i] - r[i]*cs;
v += PI*h*h*(r[i]- h / 3.0);
}
printf("%.3lf\n", v);
}
}
return 0;
}
数学真有趣