2016 Multi-University Training Contest 1 1011 tetrahedron

題目鏈接:點擊打開鏈接

題目大意:求一個四面體的內切圓半徑及圓心空間位置

解題思路:

    四面體兩條相對的邊處於兩條互相歪斜(在三維空間中既不相交也不平行,等價於異面)的直線上,所以四面體相對邊之間的距離就被定義爲其所在     互相歪斜的直線之間的距離。設d是四面體相對的邊a 和 b − c之間的距離,則四面體的另一個體積公式是:

{\displaystyle V={\frac {d|[\mathbf {a} \times \mathbf {(b-c)} ]|}{6}}.}V={\frac {d|[\mathbf {a} \times \mathbf {(b-c)} ]|}{6}}.

如果OABC四點能夠構成一個四面體,並且O點位於我們所定的空間直角座標系的原點,而向量abc代表着頂點A、B、C相對於O的位置,則四面體內切圓半徑可表示爲:(在以下的公式中,像a2這樣的向量的平方代表着數量積a·ab2c2也是這樣)

{\displaystyle r={\frac {6V}{|\mathbf {b} \times \mathbf {c} |+|\mathbf {c} \times \mathbf {a} |+|\mathbf {a} \times \mathbf {b} |+|(\mathbf {b} \times \mathbf {c} )+(\mathbf {c} \times \mathbf {a} )+(\mathbf {a} \times \mathbf {b} )|}}\,}r={\frac {6V}{|\mathbf {b} \times \mathbf {c} |+|\mathbf {c} \times \mathbf {a} |+|\mathbf {a} \times \mathbf {b} |+|(\mathbf {b} \times \mathbf {c} )+(\mathbf {c} \times \mathbf {a} )+(\mathbf {a} \times \mathbf {b} )|}}\,

內心:

{\displaystyle \mathbf {I} ={\frac {|\mathbf {b} \times \mathbf {c} |\,\mathbf {a} +|\mathbf {c} \times \mathbf {a} |\,\mathbf {b} +|\mathbf {a} \times \mathbf {b} |\,\mathbf {c} }{|\mathbf {b} \times \mathbf {c} |+|\mathbf {c} \times \mathbf {a} |+|\mathbf {a} \times \mathbf {b} |+|\mathbf {b} \times \mathbf {c} +\mathbf {c} \times \mathbf {a} +\mathbf {a} \times \mathbf {b} |}}.\,}\mathbf {I} ={\frac {|\mathbf {b} \times \mathbf {c} |\,\mathbf {a} +|\mathbf {c} \times \mathbf {a} |\,\mathbf {b} +|\mathbf {a} \times \mathbf {b} |\,\mathbf {c} }{|\mathbf {b} \times \mathbf {c} |+|\mathbf {c} \times \mathbf {a} |+|\mathbf {a} \times \mathbf {b} |+|\mathbf {b} \times \mathbf {c} +\mathbf {c} \times \mathbf {a} +\mathbf {a} \times \mathbf {b} |}}.\,
這三個定理就可以解決問題,剩下的就是代碼化了。
代碼:
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
struct V
{
    V(){x = y = z = 0.0;}
    V(double a, double b, double c)
    {
        x = a, y = b, z = c;
    }
    double x, y, z;
    friend V operator + (V &a, V &b)
    {
        return V(a.x+b.x, a.y+b.y, a.z+b.z);
    }
    friend V operator - (V &a, V &b)
    {
        return V(a.x-b.x, a.y-b.y, a.z-b.z);
    }
    friend double operator * (V &a, V &b)
    {
        return a.x*b.x + a.y*b.y + a.z*b.z;
    }
    friend V operator * (V &a, double &b)
    {
        return V(a.x*b, a.y*b, a.z*b);
    }
    friend V operator * (double &b, V &a)
    {
        return V(a.x*b, a.y*b, a.z*b);
    }
    friend V operator ^ (V &a, V &b)
    {
        return V(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
    }
    friend V operator / (V &a, double &b)
    {
        return V(a.x/b, a.y/b, a.z/b);
    }
};
double Abs(V a)
{
    return sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
}
double calR(V a, V b, V c)
{
    V tmp = b^c, tmp2 = c^a, tmp3 = a^b;
    double v = fabs(tmp*a);
    tmp = tmp+tmp2;
    tmp = tmp+tmp3;
    double fm = Abs(b^c) + Abs(c^a) + Abs(a^b) + Abs(tmp);
    return v/fm;
}
V calP(V a, V b, V c)
{
    V tmp = b^c, tmp2 = c^a, tmp3 = a^b;
    double v = fabs(tmp*a);
    tmp = tmp+tmp2;
    tmp = tmp+tmp3;
    double fm = Abs(b^c) + Abs(c^a) + Abs(a^b) + Abs(tmp);
    double xx = Abs(b^c), yy = Abs(c^a), zz = Abs(a^b);
    tmp = a*xx, tmp2 = b*yy, tmp3 = c*zz;
    tmp = tmp+tmp2;
    tmp = tmp+tmp3;
    return  tmp/fm;
}
int main()
{
    V p[4];
    double a, b, c;
    while (~scanf("%lf%lf%lf", &a, &b, &c))
    {
        p[0] = V(a, b, c);
        for (int i = 1; i < 4; i++)
        {
            scanf("%lf%lf%lf", &a, &b, &c);
            p[i] = V(a, b, c);
        }
        V A = p[1] - p[0];
        V B = p[2] - p[0];
        V C = p[3] - p[0];
        V CV = A^B;
        double isOK = CV*C;
        if (fabs(isOK) < eps)
        {
            puts("O O O O");
            continue;
        }
        double r = calR(A, B, C);
        V po = calP(A, B, C);
        po = po+p[0];
        printf("%.4f %.4f %.4f %.4f\n", po.x, po.y, po.z, r);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章