2016 Multi-University Training Contest 1 1011(HDU 5733 计算几何)

题目链接: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值