This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub beet-aizu/library
#include <bits/stdc++.h> using namespace std; //BEGIN CUT HERE #define EPS (1e-10) #define equals(a,b) (fabs((a)-(b)) < EPS) #define PI 3.141592653589793238 struct Point3D{ double x,y,z; Point3D(){} Point3D(double x,double y,double z):x(x),y(y),z(z){} Point3D operator+(Point3D p) {return Point3D(x+p.x,y+p.y,z+p.z);} Point3D operator-(Point3D p) {return Point3D(x-p.x,y-p.y,z-p.z);} Point3D operator*(double k){return Point3D(x*k,y*k,z*k);} Point3D operator/(double k){return Point3D(x/k,y/k,z/k);} Point3D operator*(Point3D p){ return Point3D(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x); } double operator^(Point3D p){ return x*p.x+y*p.y+z*p.z; } double norm(){return x*x+y*y+z*z;} double abs(){return sqrt(norm());} bool operator < (const Point3D &p) const{ if(x!=p.x) return x<p.x; if(y!=p.y) return y<p.y; return z<p.z; } bool operator == (const Point3D &p) const{ return fabs(x-p.x)<EPS and fabs(y-p.y)<EPS and fabs(z-p.z)<EPS; } }; istream &operator >> (istream &is,Point3D &p){ is>>p.x>>p.y>>p.z; return is; } ostream &operator << (ostream &os,Point3D p){ os<<fixed<<setprecision(12)<<p.x<<" "<<p.y<<" "<<p.z; return os; } typedef Point3D Vector3D; typedef vector<Point3D> Polygon3D; struct Segment3D{ Point3D p1,p2; Segment3D(){} Segment3D(Point3D p1, Point3D p2):p1(p1),p2(p2){} }; typedef Segment3D Line3D; istream &operator >> (istream &is,Segment3D &s){ is>>s.p1>>s.p2; return is; } struct Sphere{ Point3D c; double r; Sphere(){} Sphere(Point3D c,double r):c(c),r(r){} }; istream &operator >> (istream &is,Sphere &c){ is>>c.c>>c.r; return is; } double norm(Vector3D a){ return a.x*a.x+a.y*a.y+a.z*a.z; } double abs(Vector3D a){ return sqrt(norm(a)); } double dot(Vector3D a,Vector3D b){ return a.x*b.x+a.y*b.y+a.z*b.z; } Vector3D cross(Vector3D a,Vector3D b){ return Vector3D(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x); } Point3D project(Line3D l,Point3D p){ Point3D b=l.p2-l.p1; double t=dot(p-l.p1,b)/norm(b); return l.p1+b*t; } Point3D reflect(Line3D l,Point3D p){ return p+(project(l,p)-p)*2.0; } double getDistanceLP(Line3D l,Point3D p){ return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1)); } double getDistanceSP(Segment3D s,Point3D p){ if(dot(s.p2-s.p1,p-s.p1) < 0.0 ) return abs(p-s.p1); if(dot(s.p1-s.p2,p-s.p2) < 0.0 ) return abs(p-s.p2); return getDistanceLP(s,p); } bool intersectSC(Segment3D s,Sphere c){ double d=getDistanceSP(s,c.c); if(d>c.r) return 0; return !((abs(s.p1-c.c)<=c.r) and (abs(s.p2-c.c)<=c.r)); } struct ConvexHull3D{ struct face{ int a,b,c; bool ok; face(){} face(int a,int b,int c,bool ok):a(a),b(b),c(c),ok(ok){} }; int n,num; vector<Point3D> p; vector<face> f; vector<vector<int> > g; ConvexHull3D(int n):n(n),p(n),f(n*8),g(n,vector<int>(n)){} void input(){ for(int i=0;i<n;i++) cin>>p[i]; } double dblcmp(Point3D q,face f){ Point3D m=p[f.b]-p[f.a]; Point3D n=p[f.c]-p[f.a]; Point3D t=q-p[f.a]; return (m*n)^t; } void deal(int q,int a,int b){ int idx=g[a][b]; face add; if(f[idx].ok){ if(dblcmp(p[q],f[idx])>EPS) dfs(q,idx); else{ add=face(b,a,q,1); g[q][b]=g[a][q]=g[b][a]=num; f[num++]=add; } } } void dfs(int q,int now){ f[now].ok=0; deal(q,f[now].b,f[now].a); deal(q,f[now].c,f[now].b); deal(q,f[now].a,f[now].c); } void build(){ num=0; if(n<4) return; bool flg=1; for(int i=1;i<n;i++){ if(abs(p[0]-p[i])>EPS){ swap(p[1],p[i]); flg=0; break; } } if(flg) return; flg=1; for(int i=2;i<n;i++){ if(abs((p[0]-p[1])*(p[1]-p[i]))>EPS){ swap(p[2],p[i]); flg=0; break; } } if(flg) return; flg=1; for(int i=3;i<n;i++){ if(abs(((p[0]-p[1])*(p[1]-p[2]))^(p[0]-p[i]))>EPS){ swap(p[3],p[i]); flg=0; break; } } if(flg) return; face add; for(int i=0;i<4;i++){ add=face((i+1)%4,(i+2)%4,(i+3)%4,1); if(dblcmp(p[i],add)>0) swap(add.b,add.c); g[add.a][add.b]=g[add.b][add.c]=g[add.c][add.a]=num; f[num++]=add; } for(int i=4;i<n;i++){ for(int j=0;j<num;j++){ if(f[j].ok and dblcmp(p[i],f[j])>EPS){ dfs(i,j); break; } } } int tmp=num; num=0; for(int i=0;i<tmp;i++) if(f[i].ok) f[num++]=f[i]; } double volume(Point3D a,Point3D b,Point3D c,Point3D d){ return ((b-a)*(c-a))^(d-a); } bool same(int s,int t){ Point3D &a=p[f[s].a]; Point3D &b=p[f[s].b]; Point3D &c=p[f[s].c]; return (abs(volume(a,b,c,p[f[t].a]))<EPS) and (abs(volume(a,b,c,p[f[t].b]))<EPS) and (abs(volume(a,b,c,p[f[t].c]))<EPS); } int polygon(){ int res=0; for(int i=0;i<num;i++){ int flg=1; for(int j=0;j<i;j++) flg&=!same(i,j); res+=flg; } return res; } int triangle(){ return num; } double area(Point3D a,Point3D b,Point3D c){ return abs((b-a)*(c-a)); } Point3D cross(Point3D a,Point3D b,Point3D c){ return Point3D((b.y-a.y)*(c.z-a.z)-(b.z-a.z)*(c.y-a.y), (b.z-a.z)*(c.x-a.x)-(b.x-a.x)*(c.z-a.z), (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x)); } double area(){ double res=0; if(n==3){ Point3D q=cross(p[0],p[1],p[2]); res=abs(q)/2.0; return res; } return res; for(int i=0;i<num;i++) res+=area(p[f[i].a],p[f[i].b],p[f[i].c]); return res/2.0; } }; //END CUT HERE signed main(){ int n; while(cin>>n){ ConvexHull3D ch(n); ch.input(); ch.build(); cout<<ch.polygon()<<endl; } return 0; } /* verified on 2019/10/22 https://vjudge.net/problem/HDU-3662 */
#line 1 "geometry/3D/geometry3D.cpp" #include <bits/stdc++.h> using namespace std; //BEGIN CUT HERE #define EPS (1e-10) #define equals(a,b) (fabs((a)-(b)) < EPS) #define PI 3.141592653589793238 struct Point3D{ double x,y,z; Point3D(){} Point3D(double x,double y,double z):x(x),y(y),z(z){} Point3D operator+(Point3D p) {return Point3D(x+p.x,y+p.y,z+p.z);} Point3D operator-(Point3D p) {return Point3D(x-p.x,y-p.y,z-p.z);} Point3D operator*(double k){return Point3D(x*k,y*k,z*k);} Point3D operator/(double k){return Point3D(x/k,y/k,z/k);} Point3D operator*(Point3D p){ return Point3D(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x); } double operator^(Point3D p){ return x*p.x+y*p.y+z*p.z; } double norm(){return x*x+y*y+z*z;} double abs(){return sqrt(norm());} bool operator < (const Point3D &p) const{ if(x!=p.x) return x<p.x; if(y!=p.y) return y<p.y; return z<p.z; } bool operator == (const Point3D &p) const{ return fabs(x-p.x)<EPS and fabs(y-p.y)<EPS and fabs(z-p.z)<EPS; } }; istream &operator >> (istream &is,Point3D &p){ is>>p.x>>p.y>>p.z; return is; } ostream &operator << (ostream &os,Point3D p){ os<<fixed<<setprecision(12)<<p.x<<" "<<p.y<<" "<<p.z; return os; } typedef Point3D Vector3D; typedef vector<Point3D> Polygon3D; struct Segment3D{ Point3D p1,p2; Segment3D(){} Segment3D(Point3D p1, Point3D p2):p1(p1),p2(p2){} }; typedef Segment3D Line3D; istream &operator >> (istream &is,Segment3D &s){ is>>s.p1>>s.p2; return is; } struct Sphere{ Point3D c; double r; Sphere(){} Sphere(Point3D c,double r):c(c),r(r){} }; istream &operator >> (istream &is,Sphere &c){ is>>c.c>>c.r; return is; } double norm(Vector3D a){ return a.x*a.x+a.y*a.y+a.z*a.z; } double abs(Vector3D a){ return sqrt(norm(a)); } double dot(Vector3D a,Vector3D b){ return a.x*b.x+a.y*b.y+a.z*b.z; } Vector3D cross(Vector3D a,Vector3D b){ return Vector3D(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x); } Point3D project(Line3D l,Point3D p){ Point3D b=l.p2-l.p1; double t=dot(p-l.p1,b)/norm(b); return l.p1+b*t; } Point3D reflect(Line3D l,Point3D p){ return p+(project(l,p)-p)*2.0; } double getDistanceLP(Line3D l,Point3D p){ return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1)); } double getDistanceSP(Segment3D s,Point3D p){ if(dot(s.p2-s.p1,p-s.p1) < 0.0 ) return abs(p-s.p1); if(dot(s.p1-s.p2,p-s.p2) < 0.0 ) return abs(p-s.p2); return getDistanceLP(s,p); } bool intersectSC(Segment3D s,Sphere c){ double d=getDistanceSP(s,c.c); if(d>c.r) return 0; return !((abs(s.p1-c.c)<=c.r) and (abs(s.p2-c.c)<=c.r)); } struct ConvexHull3D{ struct face{ int a,b,c; bool ok; face(){} face(int a,int b,int c,bool ok):a(a),b(b),c(c),ok(ok){} }; int n,num; vector<Point3D> p; vector<face> f; vector<vector<int> > g; ConvexHull3D(int n):n(n),p(n),f(n*8),g(n,vector<int>(n)){} void input(){ for(int i=0;i<n;i++) cin>>p[i]; } double dblcmp(Point3D q,face f){ Point3D m=p[f.b]-p[f.a]; Point3D n=p[f.c]-p[f.a]; Point3D t=q-p[f.a]; return (m*n)^t; } void deal(int q,int a,int b){ int idx=g[a][b]; face add; if(f[idx].ok){ if(dblcmp(p[q],f[idx])>EPS) dfs(q,idx); else{ add=face(b,a,q,1); g[q][b]=g[a][q]=g[b][a]=num; f[num++]=add; } } } void dfs(int q,int now){ f[now].ok=0; deal(q,f[now].b,f[now].a); deal(q,f[now].c,f[now].b); deal(q,f[now].a,f[now].c); } void build(){ num=0; if(n<4) return; bool flg=1; for(int i=1;i<n;i++){ if(abs(p[0]-p[i])>EPS){ swap(p[1],p[i]); flg=0; break; } } if(flg) return; flg=1; for(int i=2;i<n;i++){ if(abs((p[0]-p[1])*(p[1]-p[i]))>EPS){ swap(p[2],p[i]); flg=0; break; } } if(flg) return; flg=1; for(int i=3;i<n;i++){ if(abs(((p[0]-p[1])*(p[1]-p[2]))^(p[0]-p[i]))>EPS){ swap(p[3],p[i]); flg=0; break; } } if(flg) return; face add; for(int i=0;i<4;i++){ add=face((i+1)%4,(i+2)%4,(i+3)%4,1); if(dblcmp(p[i],add)>0) swap(add.b,add.c); g[add.a][add.b]=g[add.b][add.c]=g[add.c][add.a]=num; f[num++]=add; } for(int i=4;i<n;i++){ for(int j=0;j<num;j++){ if(f[j].ok and dblcmp(p[i],f[j])>EPS){ dfs(i,j); break; } } } int tmp=num; num=0; for(int i=0;i<tmp;i++) if(f[i].ok) f[num++]=f[i]; } double volume(Point3D a,Point3D b,Point3D c,Point3D d){ return ((b-a)*(c-a))^(d-a); } bool same(int s,int t){ Point3D &a=p[f[s].a]; Point3D &b=p[f[s].b]; Point3D &c=p[f[s].c]; return (abs(volume(a,b,c,p[f[t].a]))<EPS) and (abs(volume(a,b,c,p[f[t].b]))<EPS) and (abs(volume(a,b,c,p[f[t].c]))<EPS); } int polygon(){ int res=0; for(int i=0;i<num;i++){ int flg=1; for(int j=0;j<i;j++) flg&=!same(i,j); res+=flg; } return res; } int triangle(){ return num; } double area(Point3D a,Point3D b,Point3D c){ return abs((b-a)*(c-a)); } Point3D cross(Point3D a,Point3D b,Point3D c){ return Point3D((b.y-a.y)*(c.z-a.z)-(b.z-a.z)*(c.y-a.y), (b.z-a.z)*(c.x-a.x)-(b.x-a.x)*(c.z-a.z), (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x)); } double area(){ double res=0; if(n==3){ Point3D q=cross(p[0],p[1],p[2]); res=abs(q)/2.0; return res; } return res; for(int i=0;i<num;i++) res+=area(p[f[i].a],p[f[i].b],p[f[i].c]); return res/2.0; } }; //END CUT HERE signed main(){ int n; while(cin>>n){ ConvexHull3D ch(n); ch.input(); ch.build(); cout<<ch.polygon()<<endl; } return 0; } /* verified on 2019/10/22 https://vjudge.net/problem/HDU-3662 */