Girlfriend(2021牛客多校第二场F)

题目描述

在这里插入图片描述

输入描述

在这里插入图片描述

输出描述

在这里插入图片描述

输入样例

1
1 0 0
3 0 0
2 0 0
4 0 0
3 3

输出样例

0.262

数据范围

在这里插入图片描述


一个非常有意思(?)的题面,由题意不难看出所求为两人所在次元 (球)的体积交。而限制条件 |AP1| ≥ k|BP1| 可转换为阿氏圆进行求解,对应到三维立体空间即为所求的球。

解题思路即为->求两球的球心和半径->求两球的体积交;

我们可以通过对应的比例关系求出在 AB 直线上可存在的两点 P1 ,由阿氏圆的性质可得,两点间距离的一半即为半径 r ,两点间的中点即为球心。

而求直线上P1的公式为:

b-lab/(k+1);
b+lab*k/(k-1);

(其中b,lab为对应方向坐标及对应方向向量)

求出两球之后,我们可通过判断半径及球心距确认两球的位置关系,当两球相交时,可通过球冠算出体积交;当两球不相交时,直接输出0即可;当两球内含时,输出较小球的体积;

参考代码

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
typedef long double ld;
const double PI = acos(-1);
 
 
struct pos
{
    ld x,y,z;
};
int T;
pos p[5];
ld k1,k2;
 
void calc(pos o1,pos o2,ld r1,ld r2)
{
 
    double ans=0.0;
    double dis=sqrt((o1.x-o2.x)*(o1.x-o2.x)+(o1.y-o2.y)*(o1.y-o2.y)+(o1.z-o2.z)*(o1.z-o2.z));
 
    //不相交
    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
    {
        double cos_r1_dis=(r1*r1+dis*dis-r2*r2)/(2.0*dis*r1);
 
        double h1=r1-r1*cos_r1_dis;
 
        ans+=(1.0/3.0)*PI*h1*h1*(3.0*r1-h1);
 
        double cos_r2_dis=(r2*r2+dis*dis-r1*r1)/(2.0*dis*r2);
 
        double h2=r2-r2*cos_r2_dis;
 
        ans+=(1.0/3.0)*PI*h2*h2*(3.0*r2-h2);
    }
    printf("%.3f\n",ans);
}
 
int main()
{
    cin>>T;
    while(T--)
    {
        for(int i = 0; i < 4; i++)
            cin >> p[i].x >> p[i].y >> p[i].z;
 
        cin>>k1>>k2;
        double tmp1=k1*k1-1,tmp2=k2*k2-1;
 
        pos O1,O2;
        double r1,r2,D1,D2;
 
        //球1
        O1.x=(k1*k1*p[1].x-p[0].x)/tmp1;
        O1.y=(k1*k1*p[1].y-p[0].y)/tmp1;
        O1.z=(k1*k1*p[1].z-p[0].z)/tmp1;
 
 
        D1=k1*k1*((p[1].x*p[1].x)+(p[1].y*p[1].y)+(p[1].z*p[1].z))-p[0].x*p[0].x-p[0].y*p[0].y-p[0].z*p[0].z;
        D1/=tmp1;
 
        r1=sqrt(O1.x*O1.x+O1.y*O1.y+O1.z*O1.z-D1);
 
        //球2
        O2.x=(k2*k2*p[3].x-p[2].x)/tmp2;
        O2.y=(k2*k2*p[3].y-p[2].y)/tmp2;
        O2.z=(k2*k2*p[3].z-p[2].z)/tmp2;
 
 
        D2=k2*k2*(p[3].x*p[3].x+p[3].y*p[3].y+p[3].z*p[3].z)-p[2].x*p[2].x-p[2].y*p[2].y-p[2].z*p[2].z;
        D2/=tmp2;
 
        r2=sqrt(O2.x*O2.x+O2.y*O2.y+O2.z*O2.z-D2);
        calc(O1,O2,r1,r2);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值