题目链接:
题意:求三维凸包表面积。
思路:模板。
struct Point{ double x,y,z; Point() {} Point(double _x,double _y,double _z) { x=_x; y=_y; z=_z; } void Get() { RD(x,y,z); } Point operator-(const Point p1) { return Point(x-p1.x,y-p1.y,z-p1.z); } Point operator*(Point p) { return Point(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x); } double operator^(Point p) { return x*p.x+y*p.y+z*p.z; } double len() { return sqrt(sqr(x)+sqr(y)+sqr(z)); }};struct _3DCH{ struct face { int a,b,c,ok; face(){} face(int _a,int _b,int _c,int _ok) { a=_a; b=_b; c=_c; ok=_ok; } }F[N<<2]; int n,cnt,b[N][N]; Point p[N]; int DB(double x) { if(x>1e-10) return 1; if(x<-1e-10) return -1; return 0; } double vlen(Point a) { return a.len(); } double getArea(Point a,Point b,Point c) { return vlen((b-a)*(c-a)); } double getVolume(Point a,Point b,Point c,Point d) { return (b-a)*(c-a)^(d-a); } //t在f的正面返回1,反面返回-1,在f上返回0 int getDir(Point t,face f) { double x=(p[f.b]-p[f.a])*(p[f.c]-p[f.a])^(t-p[f.a]); return DB(x); } void deal(int i,int x,int y) { int f=b[x][y]; face temp; if(!F[f].ok) return; if(getDir(p[i],F[f])>0) DFS(i,f); else { temp=face(y,x,i,1); b[y][x]=b[x][i]=b[i][y]=cnt; F[cnt++]=temp; } } void DFS(int i,int j) { F[j].ok=0; deal(i,F[j].b,F[j].a); deal(i,F[j].c,F[j].b); deal(i,F[j].a,F[j].c); } void construct() { if(n<4) return; int i,j,k=0; FOR1(i,n-1) if(DB(vlen(p[0]-p[i]))) { swap(p[1],p[i]); k=1; break; } if(!k) return; k=0; FOR(i,2,n-1) if(DB(getArea(p[0],p[1],p[i]))) { swap(p[2],p[i]); k=1; break; } if(!k) return;; k=0; FOR(i,3,n-1) if(DB(getVolume(p[0],p[1],p[2],p[i]))) { swap(p[3],p[i]); k=1; break; } if(!k) return; cnt=0; face temp; FOR0(i,4) { temp=face((i+1)%4,(i+2)%4,(i+3)%4,1); if(getDir(p[i],temp)>0) swap(temp.b,temp.c); b[temp.a][temp.b]=b[temp.b][temp.c]=b[temp.c][temp.a]=cnt; F[cnt++]=temp; } FOR(i,4,n-1) FOR0(j,cnt) if(F[j].ok&&getDir(p[i],F[j])>0) { DFS(i,j); break; } j=0; FOR0(i,cnt) if(F[i].ok) F[j++]=F[i]; cnt=j; } double getSumArea() { double ans=0; int i; FOR0(i,cnt) ans+=getArea(p[F[i].a],p[F[i].b],p[F[i].c]); return ans/2; }};_3DCH a;int main(){ while(scanf("%d",&a.n)!=-1) { int i; FOR0(i,a.n) a.p[i].Get(); a.construct(); double s=a.getSumArea(); printf("%.3lf\n",s); } return 0;}