tetrahedron
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 569 Accepted Submission(s): 219
Problem Description
Given four points ABCD, if ABCD is a tetrahedron, calculate the inscribed sphere of ABCD.
Input
Multiple test cases (test cases ≤100).
Each test cases contains a line of 12 integers [−1e6,1e6] indicate the coordinates of four vertices of ABCD.
Input ends by EOF.
Output
Print the coordinate of the center of the sphere and the radius, rounded to 4 decimal places.
If there is no such sphere, output “O O O O”.
Sample Input
0 0 0 2 0 0 0 0 2 0 2 0
0 0 0 2 0 0 3 0 0 4 0 0
Sample Output
0.4226 0.4226 0.4226 0.4226
O O O O
Author
HIT
Source
2016 Multi-University Training Contest 1
题意:给你四个点,让你判断是否能形成四面体,如果能形成,求出内切球球心和半径。
思路:因为四个点有可能会形不成四面体,当发生这种情况的时候,肯定会有至少3个点在同一平面,所以说我们要先确定一个平面,然后判断四点共面
1.任取三个点,判断是否共线,如果存在3个点共线,则必不可能形成四面体。
2.当满足1后,判断第四个顶点距离底面的距离,如果小于eps,说明四点共面,则必不可能形成四面体,点面距离公式为:
ac代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXN 1010000
#define LL long long
#define ll __int64
#define INF 0x7fffffff
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-8
using namespace std;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
double dpow(double a,ll b){double ans=1.0;while(b){if(b%2)ans=ans*a;a=a*a;b/=2;}return ans;}
//head
struct s
{
double x,y,z;
};
s a,b,c,d;
//距离
double dis(s A,s B)
{
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)+(A.z-B.z)*(A.z-B.z));
}
//叉积AxB
s cross(s A,s B)
{
s n;
n.x=A.y*B.z-A.z*B.y;
n.y=A.z*B.x-A.x*B.z;
n.z=A.x*B.y-A.y*B.x;
return n;
}
//点积
double point_m(s A,s B)
{
double ans=A.x*B.x+A.y*B.y+A.z*B.z;
return ans;
}
//判断三点共线
bool check(s A,s B,s C)
{
double distarr[5];
distarr[0]=dis(A,B);
distarr[1]=dis(A,C);
distarr[2]=dis(B,C);
sort(distarr,distarr+3);
return fabs(distarr[0]+distarr[1]-distarr[2])s A,s B,s C,s D)
{
s a1;a1.x=A.x-B.x,a1.y=A.y-B.y,a1.z=A.z-B.z;
s a2;a2.x=B.x-C.x,a2.y=B.y-C.y,a2.z=B.z-C.z;
s n=cross(a1,a2);//法向量
s up;up.x=D.x-A.x;up.y=D.y-A.y;up.z=D.z-A.z;
double aa=point_m(up,n);
double bb=point_m(n,n);
return fabs(aa/sqrt(bb));
}
//三角形面积
double area(s A,s B,s C)
{
double ba=dis(B,C);
double bb=dis(A,C);
double bc=dis(B,A);
double p=(ba+bb+bc)/2.0;
return sqrt(p*(p-ba)*(p-bb)*(p-bc));
}
int main()
{
while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&a.z,&b.x,&b.y,&b.z,&c.x,&c.y,&c.z,&d.x,&d.y,&d.z)!=EOF)
{
if(check(a,b,c)||check(a,b,d)||check(a,c,d)||check(b,c,d))
{
printf("O O O O\n");
continue;
}
else if(dis_D(a,b,c,d)printf("O O O O\n");
continue;
}
double sa=area(b,c,d);
double sb=area(a,c,d);
double sc=area(a,b,d);
double sd=area(a,b,c);
double sum=sa+sb+sc+sd;
s ans;double l=dis_D(a,b,c,d);
ans.x=(sa*a.x+sb*b.x+sc*c.x+sd*d.x)/sum;
ans.y=(sa*a.y+sb*b.y+sc*c.y+sd*d.y)/sum;
ans.z=(sa*a.z+sb*b.z+sc*c.z+sd*d.z)/sum;
double la=dis(a,b)*dis(a,b),lb=dis(a,d)*dis(a,d),lc=dis(a,c)*dis(a,c),ld=dis(c,d)*dis(c,d),le=dis(b,c)*dis(b,c),lf=dis(b,d)*dis(b,d);
double V=sqrt(la*ld*(lb+lc+le+lf-la-ld)+lb*le*(la+lc+ld+lf-lb-le)+lc*lf*(la+lb+ld+le-lc-lf)-la*lb*lf-lb*lc*ld-lc*la*le-ld*le*lf)/4.0;
double R=V/sum;
printf("%.4lf %.4lf %.4lf %.4lf\n",ans.x,ans.y,ans.z,R);
}
return 0;
}