F Girlfriend (阿波罗尼斯球+简单几何)
题目大意:
给定四个点,每两个点构成一个阿波罗尼斯球,求两圆相交部分的体积。
思路:
一看就是几何题啊,话不多说直接开淦。。。
首先对于阿波罗尼斯球的性质得到
∣
P
A
∣
=
=
K
∗
∣
P
B
∣
|PA| == K*|PB|
∣PA∣==K∗∣PB∣
假设
A
(
x
0
,
y
0
,
z
0
)
A(x_0,y_0,z_0)
A(x0,y0,z0),
B
(
x
1
,
y
1
,
z
1
)
B(x_1,y_1,z_1)
B(x1,y1,z1)那么我们有:
( x − x 0 ) 2 + ( y − y 0 ) 2 + ( z − z 0 ) 2 = k ∗ k ∗ ( ( x − x 1 ) 2 + ( y − y 1 ) 2 + ( z − z 1 ) 2 ) (x-x_0)^2+(y-y_0)^2+(z-z_0)^2=k*k*((x-x_1)^2+(y-y_1)^2+(z-z_1)^2) (x−x0)2+(y−y0)2+(z−z0)2=k∗k∗((x−x1)2+(y−y1)2+(z−z1)2)
整理得:
( 1 − k 2 ) ∗ x 2 + ( 1 − k 2 ) ∗ y 2 + ( 1 − k 2 ) ∗ z 2 + ( 2 ∗ k 2 ∗ x 1 − 2 ∗ x 0 ) ∗ x + ( 2 ∗ k 2 ∗ y 1 − 2 ∗ y 0 ) ∗ y + ( 2 ∗ k 2 ∗ z 1 − 2 ∗ z 0 ) ∗ z + x 0 2 + y 0 2 + z 0 2 − k 2 ( x 1 2 + y 1 2 + z 1 2 ) = 0 (1-k^2)*x^2+(1-k^2)*y^2+(1-k^2)*z^2+(2*k^2*x_1-2*x_0)*x+(2*k^2*y_1-2*y_0)*y+(2*k^2*z_1-2*z_0)*z+x_0^2+y_0^2+z_0^2-k^2(x_1^2+y_1^2+z_1^2) = 0 (1−k2)∗x2+(1−k2)∗y2+(1−k2)∗z2+(2∗k2∗x1−2∗x0)∗x+(2∗k2∗y1−2∗y0)∗y+(2∗k2∗z1−2∗z0)∗z+x02+y02+z02−k2(x12+y12+z12)=0
由一般球的展开式可得:
x
2
+
y
2
+
z
2
+
2
a
x
+
2
b
y
+
2
c
z
+
d
=
0
x^2+y^2+z^2+2ax+2by+2cz+d=0
x2+y2+z2+2ax+2by+2cz+d=0
整理得:
(
x
+
a
)
2
+
(
y
+
b
)
2
+
(
z
+
c
)
2
=
a
2
+
b
2
+
c
2
−
d
(x+a)^2+(y + b)^2+(z + c)^2=a^2+b^2+c^2-d
(x+a)2+(y+b)2+(z+c)2=a2+b2+c2−d
自此,我们其实做完了第一步准备工作,也就是求出固定k值球的半径。
r
=
a
2
+
b
2
+
c
2
−
d
r=\sqrt {a^2+b^2+c^2-d}
r=a2+b2+c2−d
接下来我们要判断两球的位置,对于相离,内切,内含的情况,我们可以非常容易的求出其相交的体积,对于相交情况我们需要一个结论。
我们将两个球分开来看
对于这个球,我们要求
∣
j
k
∣
|jk|
∣jk∣以上部分的体积
(一)
由三重积分先面后线可得:
V
=
∫
r
−
h
r
π
∗
y
2
d
z
V=\int_{r-h}^r{π*y^2dz}
V=∫r−hrπ∗y2dz
而
z
2
+
y
2
=
r
2
z^2+y^2=r^2
z2+y2=r2
所以有
V
=
∫
r
−
h
r
π
∗
(
r
2
−
z
2
)
d
y
V=\int_{r-h}^r{π*(r^2-z^2)dy}
V=∫r−hrπ∗(r2−z2)dy
得
V
=
π
h
2
(
r
−
h
/
3
)
V = πh^2(r-h/3)
V=πh2(r−h/3)
(二)
可以由二重积分推导:
V
=
∬
R
2
−
x
2
−
y
2
−
(
R
−
h
)
d
x
d
y
V=\iint\sqrt{R^2-x^2-y^2}-(R-h)dxdy
V=∬R2−x2−y2−(R−h)dxdy
利用极坐标形式进行代换:
V
=
∫
0
2
π
d
θ
∫
0
2
R
h
−
h
2
(
R
2
−
ρ
2
−
(
R
−
h
)
)
ρ
d
ρ
V=\int_{0}^{2π}dθ\int_{0}^{\sqrt{2Rh-h^2}}(\sqrt{R^2-ρ^2}-(R-h))ρdρ
V=∫02πdθ∫02Rh−h2(R2−ρ2−(R−h))ρdρ
整理上式也可得到相同结果。
至此所有的公式我们都已经推导出来,一一计算输出即可。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<queue>
#define pi 3.1415926535
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e6 + 10;
void volume(double r1x, double r1y, double r1z, double r2x, double r2y, double r2z, double r1, double r2) {
double d = sqrt((r1x - r2x) * (r1x - r2x) + (r1y - r2y) * (r1y - r2y) + (r1z - r2z) * (r1z - r2z));
if (d >= r1 + r2) {
printf("%.3lf\n", 0);
}
else if (d + r2 <= r1) {
printf("%.3lf\n", 4 * 1.0 / 3 * 1.0 * pi * r2 * r2 * r2);
}
else if (d + r1 <= r2) {
printf("%.3lf\n", 4 * 1.0 / 3 * 1.0 * pi * r1 * r1 * r1);
}
else {
double ans = 0;
double cosa = (r1 * r1 + d * d - r2 * r2) / (2.0 * r1 * d);
double h1 = r1 - r1 * cosa;
ans += pi * h1 * h1 * (r1 - h1 / 3.0);
double cosb = (r2 * r2 + d * d - r1 * r1) / (2.0 * r2 * d);
double h2 = r2 - r2 * cosb;
ans += pi * h2 * h2 * (r2 - h2 / 3.0);
printf("%.3lf\n", ans);
}
}
int main() {
double x[5], y[5], z[5];
int t;
cin >> t;
while (t--)
{
for (int i = 1; i <= 4; i++) {
cin >> x[i] >> y[i] >> z[i];
}
double k1, k2;
cin >> k1 >> k2;
double dishu1 = 1 - k1 * k1;
double a1 = (k1 * k1 * x[2] - x[1]) / dishu1, b1 = (k1 * k1 * y[2] - y[1]) / dishu1, c1 = (k1 * k1 * z[2] - z[1]) / dishu1;
double d1 = ((x[1] * x[1] + y[1] * y[1] + z[1] * z[1]) - (k1 * k1 * (x[2] * x[2] + y[2] * y[2] + z[2] * z[2]))) / dishu1;
double r1 = sqrt(a1 * a1 + b1 * b1 + c1 * c1 - d1);
double dishu2 = 1 - k2 * k2;
double a2 = (k2 * k2 * x[4] - x[3]) / dishu2, b2 = (k2 * k2 * y[4] - y[3]) / dishu2, c2 = (k2 * k2 * z[4] - z[3]) / dishu2;
double d2 = ((x[3] * x[3] + y[3] * y[3] + z[3] * z[3]) - (k2 * k2 * (x[4] * x[4] + y[4] * y[4] + z[4] * z[4]))) / dishu2;
double r2 = sqrt(a2 * a2 + b2 * b2 + c2 * c2 - d2);
volume(a1, b1, c1, a2, b2, c2, r1, r2);
}
}