题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5733;
题目大意:给出四个三维的点,若这四个点能组成一个四面体,就求其内切球球心和半径,不能就输出O O O O;
分析:本题这主要在于先判断是否四点共面,不是的话就一定能组成四面体,然后套用四面体内心公式和四面体内切圆半径公式就可以求出.
代码如下:
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <utility>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
const int MAXN=100005;
const double eps=1e-7;
const double pi=acos(-1.0);
#define zero(x) (((x)>0?(x):-(x))<eps)
int dcmp(double x){
if(fabs(x)<eps)return 0;
if(x>0)return 1;
return -1;
} //因为精度的问题,在这里求减法的精度
struct Point{
double x,y,z;
Point(){}
Point(double _x,double _y,double _z){
x=_x,y=_y,z=_z;
} //所在的图形
};//求解点积
struct Line{
Point a,b;
Line(){}
Line(Point _a,Point _b){
a=_a;
b=_b;
}
};
struct Pline{
Point a,b,c;
Pline(){}
Pline(Point _a,Point _b,Point _c){
a=_a;
b=_b;
c=_c;
}
};
Point sub(Point a,Point b){
return Point(a.x-b.x,a.y-b.y,a.z-b.z);
}//求差
Point xmult(Point u,Point v){
return Point(u.y*v.z-v.y*u.z,u.z*v.x-u.x*v.z,u.x*v.y-v.x*u.y);
}//叉积
double dmult(Point u,Point v){
return u.x * v.x + u.y * v.y + u.z * v.z;
}//点积
Point pvec(Pline s){
return xmult(sub(s.a,s.b),sub(s.b,s.c));
}//求法向量
int dots(Point a,Point b,Point c,Point d){
Pline ss=Pline(a,b,c);
return zero(dmult(pvec(ss),sub(d,a)));
}//判断四点共面
double dis(Point a,Point b){
Point ss=sub(a,b);
return sqrt(ss.x*ss.x+ss.y*ss.y+ss.z*ss.z);
}//求两点间距离
double Area(double a,double b,double c){
double p=(a+b+c)/2;
return sqrt(p*(p-a)*(p-b)*(p-c));
}//求三角形面积(海伦公式/秦九韶公式)
int main(){
Point a,b,c,d;
while(scanf("%lf%lf%lf",&a.x,&a.y,&a.z)!=EOF){
scanf("%lf%lf%lf",&b.x,&b.y,&b.z);
scanf("%lf%lf%lf",&c.x,&c.y,&c.z);
scanf("%lf%lf%lf",&d.x,&d.y,&d.z);
if(dots(a,b,c,d)){
puts("O O O O");
continue;
}
double f[10];
f[1]=dis(a,b);
f[2]=dis(a,c);
f[3]=dis(a,d);
f[4]=dis(b,c);
f[5]=dis(b,d);
f[6]=dis(c,d);//各个边长
double tr11,tr2,tr3,tr4;
tr11=acos((f[3]*f[3]+f[2]*f[2]-f[6]*f[6])/(2*f[2]*f[3]));
tr2=acos((f[1]*f[1]+f[3]*f[3]-f[5]*f[5])/(2*f[1]*f[3]));
tr3=acos((f[1]*f[1]+f[2]*f[2]-f[4]*f[4])/(2*f[1]*f[2]));
tr4=(tr11+tr2+tr3)/2.0;
double sum=0;
double s1,s2,s3,s4;
// abc
s1=Area(f[1],f[4],f[2]);//三角形abc面积
// abd
s2=Area(f[1],f[5],f[3]);//***
// acd
s3=Area(f[2],f[3],f[6]);//***
// bcd
s4=Area(f[4],f[6],f[5]);//***
double tmp=sqrt(sin(tr4)*sin(tr4-tr11)*sin(tr4-tr2)*sin(tr4-tr3));
double ans=f[1]*f[2]*f[3]*tmp/3;//四面体体积公式
sum=s1+s2+s3+s4;
double r=3*ans/sum;//四面体内切球半径公式
double x1,y1,z1;
x1=(s1*d.x+s2*c.x+s3*b.x+s4*a.x)/sum;
y1=(s1*d.y+s2*c.y+s3*b.y+s4*a.y)/sum;
z1=(s1*d.z+s2*c.z+s3*b.z+s4*a.z)/sum;//四面体内心公式
printf("%.4f %.4f %.4f %.4f\n",x1,y1,z1,r);
}
return 0;
}