2021牛客暑期多校训练营2-F:Girlfriend

题目链接

题意:给定A,B,C,D,四个点和系数K1,K2,集合X中的点满足|A-X|>=K1|B-X|,集合Y中的点满足|C-Y|>=K2|D-Y|,求集合Z=X∩Y的大小

大学狗先梦回高中求下几何:
我们现在二维平面下求下形状

先从网上盗了个图,将就看下一:
在这里插入图片描述
前提条件
PA/PB=K
PM为∠APB的角平分线,有角平分线定理可得PA/PB=AM/MB
PN为∠APB外角的角平分线,我们过B点做一条直线PM平行线交AP于E,使得BE//PN
证明:
∵PN//BE,PM为∠APB外角的角平分线
∴∠MPB=∠PBE,∠PEB=∠MPE
∴PE=PB
∵PE/PA=NB/NA,PE=PB
∴PB/PA=NB/NA=MB/MA=1/K
∵PM,PN为角平分线
∴∠MPN为直角
∴P的轨迹为圆

我们上面得到了PB/PA=NB/NA=MB/MA=1/K,且P的运动轨迹为一个圆,现在可以来确定圆的圆心和半径大小了
假定A(Xa,Ya),B(Xb,Yb),设P(x,y),带入|AP|=K|BP|,解出圆心为( k ∗ k ∗ x 2 − x 1 k ∗ k − 1 k*k*x2-x1 \over k*k-1 kk1kkx2x1 k ∗ k ∗ y 2 − y 1 k ∗ k − 1 k*k*y2-y1 \over k*k-1 kk1kky2y1),r= k ∣ a b ∣ k ∗ k − 1 k|ab| \over k*k-1 kk1kab

题目是:|A-X|>=K1|B-X|,所以这题不是二维的圆,而是三维的球,圆心为( k ∗ k ∗ x 2 − x 1 k ∗ k − 1 k*k*x2-x1 \over k*k-1 kk1kkx2x1 k ∗ k ∗ y 2 − y 1 k ∗ k − 1 k*k*y2-y1 \over k*k-1 kk1kky2y1 k ∗ k ∗ z 2 − z 1 k ∗ k − 1 k*k*z2-z1 \over k*k-1 kk1kkz2z1),r= k ∣ a b ∣ k ∗ k − 1 k|ab| \over k*k-1 kk1kab
相交后的体积有三种情况:
①两球不相交,结果为0
②两球是包含关系,结果为被包含的球的体积
③两球部分相交

球缺的体积公式:π H 2 H^{2} H2(R- H 3 H \over 3 3H),详情见:这里

现在来求下第三种情况:
即较大的球的半径为R,球心为A,另一个为半径为r,球心为B,两球相交形成的圆的半径为d,D为圆上一点,则可以得到 cos ⁡ \cos cos∠BAD= R 2 R^{2} R2+ ∣ A B ∣ 2 |AB|^{2} AB2- r 2 r^{2} r2 / 2R|AB|,则h1=R*(1- cos ⁡ \cos cos∠BAD),同理可得h2

AcCode

#include<algorithm>
#include<iostream>
#include<cmath>

using namespace std;

class point {
public:
	point(double x, double y, double z) { this->x = x, this->y = y, this->z = z; };
	double getX() { return this->x; };
	double getY() { return this->y; }
	double getZ() { return this->z; }
private:
	double x;
	double y;
	double z;
};

double getDis(point a, point b) {
	double ans = sqrt(pow(a.getX() - b.getX(), 2) + pow(a.getY() - b.getY(), 2) + pow(a.getZ() - b.getZ(), 2));
	return ans;
}

point getPoint(point A, point B, double k, double k1) {
	double x1, y1, z1;
	x1 = (1.0 * k1 * k1 * B.getX() - A.getX()) / k;
	y1 = (1.0 * k1 * k1 * B.getY() - A.getY()) / k;
	z1 = (1.0 * k1 * k1 * B.getZ() - A.getZ()) / k;
	point ret(x1, y1, z1);
	return ret;
}

signed main() {
	int t;
	double pi = acos(-1);
	cin >> t;
	while (t--) {
		double x, y, z, k1, k2;
		cin >> x >> y >> z;
		point A(x, y, z);
		cin >> x >> y >> z;
		point B(x, y, z);
		cin >> x >> y >> z;
		point C(x, y, z);
		cin >> x >> y >> z;
		point D(x, y, z);
		cin >> k1 >> k2;
		double kk1 = k1 * k1 - 1;
		double kk2 = k2 * k2 - 1;
		double AB = getDis(A, B);
		double CD = getDis(C, D);
		double R1 = k1 * AB / abs(kk1);
		double R2 = k2 * CD / abs(kk2);
		point O1 = getPoint(A, B, kk1, k1);
		point O2 = getPoint(C, D, kk2, k2);
		double R = getDis(O1, O2);
		if (R >= (R1 + R2)) {
			cout << 0 << endl;
		}
		else if (R < abs(R1 - R2)) {
			double ans1 = 4.0 * pi * R1 * R1 * R1 / 3;
			double ans2 = 4.0 * pi * R2 * R2 * R2 / 3;
			cout << min(ans1, ans2) << endl;
		}
		else {
			double c1 = 1.0 * (R * R + R1 * R1 - R2 * R2) / (2 * R1 * R);
			double c2 = 1.0 * (R * R + R2 * R2 - R1 * R1) / (2 * R2 * R);
			double h1 = R1 * (1.0 - c1);
			double h2 = R2 * (1.0 - c2);
			double ans1 = pi * h1 * h1 * (R1 - h1 / 3);
			double ans2 = pi * h2 * h2 * (R2 - h2 / 3);
			cout << ans1 + ans2 << endl;
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值