HDU5733_四面体的内切球

1.前言:2018马上就要过去了,今天的一场模拟赛做到了这个题,一开始没有人过,我在队友开其他题的时候偷懒找了个题面最短的题来做,结果还真让我yy出来了。其实高数基础扎实还是很有用的哈。

2.题目链接。题意十分的裸,就是给你空间中四个点求球心的坐标以及球的半径。首先我们需要知道一些东西,半径怎么求?这个其实大家高中都会,就是等体积法,四面体的体积被表示成表面积与内切球半径的乘积的3倍。四面体的体积可以有很多种球法,我们可以使用点到平面的距离,我觉得最简单的还是混合积的六分之一好算。最后最重要的就是球心坐标的计算了。其实也很简单,就是公式,求出每个点对球心坐标的贡献,这其实是一个加权的平均数,权值就是这个点对的面的面积。为什么时是这样的?其实微积分中有答案的,不懂得同学可以翻翻书看看。我直接把我的代码拉出来:

#include<iomanip>
#include<cmath>
using namespace std;
struct P
{
	double x, y, z;
	P() {};
	P(double x, double y, double z)
	{
		this->x = x;
		this->y = y;
		this->z = z;
	}
	P operator-(const P a)
	{
		return P(a.x - x, a.y - y, a.z - z);
	}
}p[4];
double getA(P a, P b, P c)
{
	double l1 = sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y,2) + pow(a.z - b.z, 2));
	double l2 = sqrt(pow(a.x - c.x, 2) + pow(a.y - c.y, 2) + pow(a.z - c.z,2));
	double l3 = sqrt(pow(b.x - c.x, 2) + pow(b.y - c.y, 2) + pow(b.z - c.z, 2));
	double p = (l1 + l2 + l3) / 2;
	double s = sqrt(p*(p - l1)*(p - l2)*(p - l3));
	return s;
}
double getV(P a, P b, P c)
{
	double s = abs(a.x*(b.y*c.z - b.z*c.y) - a.y*(b.x*c.z - b.z*c.x) + a.z*(b.x*c.y - b.y*c.x));
	return s / 6;
}
#pragma warning(disable:4996)
int main()
{
	
	while (~scanf("%lf%lf%lf",&p[0].x,&p[0].y,&p[0].z))
	{
		for (int i = 1; i < 4; i++)
		{
			cin >> p[i].x >> p[i].y >> p[i].z;
		}
		double v = getV(p[0] - p[1], p[0] - p[2], p[0] - p[3]);
		double s1 = getA(p[0], p[1], p[2]);
		double s2 = getA(p[0], p[1], p[3]);
		double s3 = getA(p[0], p[2], p[3]);
		double s4 = getA(p[1], p[2], p[3]);
		if (v == 0)
		{
			cout << "O O O O" << endl;
		}
		else
		{
			cout << fixed << setprecision(4);
			double S = s1 + s2 + s3 + s4;
			double r = 3 * v / S;
			double x = (p[0].x*s4 + p[1].x*s3 + p[2].x*s2 + p[3].x*s1) / S;
			double y = (p[0].y*s4 + p[1].y*s3 + p[2].y*s2 + p[3].y*s1) / S;
			double z = (p[0].z*s4 + p[1].z*s3 + p[2].z*s2 + p[3].z*s1) / S;
			cout << x << " " << y << " " << z <<" "<<r<<endl;
		}
	}
    
    return 0;
}

当然了,我当时没有想这么多就交了,然后A了,其实队友说这里需要加一个eps,我当时惊出一身冷汗,觉得要贡献出1WA了。虽然侥幸过了,但是出于严谨还是需要给每一个数据加上eps,设置成1e-8就OK。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值