1.hdoj3662 3D Convex Hull
传送:http://acm.hdu.edu.cn/showproblem.php?pid=3662
题意:给出空间n个点,问凸包表面的多边形个数。
分析:rt。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=305; 4 const double eps=1e-8; 5 int sgn(double x){ 6 if (fabs(x)<eps) return 0; 7 if (x<0) return -1; 8 return 1; 9 } 10 struct point3{ 11 double x,y,z; 12 point3(double _x=0,double _y=0,double _z=0){x=_x;y=_y;z=_z;} 13 bool operator ==(const point3 &b)const{ 14 return sgn(x-b.x)==0 && sgn(y-b.y)==0 && sgn(z-b.z)==0; 15 } 16 point3 operator -(const point3 &b)const{ 17 return point3(x-b.x,y-b.y,z-b.z); 18 } 19 //点乘 20 double operator *(const point3 &b)const{ 21 return x*b.x+y*b.y+z*b.z; 22 } 23 //叉乘 24 point3 operator ^(const point3 &b)const{ 25 return point3(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x); 26 } 27 double len(){ 28 return sqrt(x*x+y*y+z*z); 29 } 30 }; 31 32 struct CH3D{ 33 struct face{ 34 int a,b,c; //表示凸包一个面的三个点的编号 35 bool ok; //表示该面是否属于最终的凸包上的面 36 }; 37 int n; //初始顶点数 38 point3 p[maxn]; 39 int num; //凸包表面三角形数 40 face f[8*maxn]; //凸包表面的三角形 41 int g[maxn][maxn]; 42 point3 cross(const point3 &a,const point3 &b,const point3 &c){ 43 return (b-a)^(c-a); 44 } 45 //四面体有向面积 *6 46 double volume(point3 a,point3 b,point3 c,point3 d){ 47 return ((b-a)^(c-a))*(d-a); 48 } 49 double dblcmp(point3 &P,face &F){ 50 point3 p1=p[F.b]-p[F.a],p2=p[F.c]-p[F.a],p3=P-p[F.a]; 51 return (p1^p2)*p3; 52 } 53 void deal(int x,int a,int b){ 54 int k=g[a][b]; 55 face add; 56 if (f[k].ok){ 57 if (dblcmp(p[x],f[k])>eps) dfs(x,k); 58 else{ 59 add.a=b; add.b=a; add.c=x; add.ok=true; 60 g[x][b]=g[a][x]=g[b][a]=num; 61 f[num++]=add; 62 } 63 } 64 } 65 //递归搜索应该从凸包中删除的面 66 void dfs(int p,int now){ 67 f[now].ok=false; 68 deal(p,f[now].b,f[now].a); 69 deal(p,f[now].c,f[now].b); 70 deal(p,f[now].a,f[now].c); 71 } 72 //构建三维凸包 73 void create(){ 74 num=0; 75 face add; 76 77 //保证前四个点不共面 78 bool flag=true; 79 for (int i=1;i<n;i++) 80 if (!(p[0]==p[i])){ 81 swap(p[1],p[i]); 82 flag=false; break; 83 } 84 if (flag) return ; 85 flag=true; 86 for (int i=2;i<n;i++) 87 if (((p[1]-p[0])^(p[i]-p[0])).len()>eps){ 88 swap(p[2],p[i]); 89 flag=false; break; 90 } 91 if (flag) return ; 92 flag=true; 93 for (int i=3;i<n;i++){ 94 if (fabs(((p[1]-p[0])^(p[2]-p[0]))*(p[i]-p[0]))>eps){ 95 swap(p[3],p[i]); 96 flag=false; break; 97 } 98 } 99 if (flag) return ; 100 101 for (int i=0;i<4;i++){ 102 add.a=(i+1)%4; add.b=(i+2)%4; add.c=(i+3)%4; add.ok=true; 103 if (dblcmp(p[i],add)>0) swap(add.b,add.c); 104 g[add.a][add.b]=g[add.b][add.c]=g[add.c][add.a]=num; 105 f[num++]=add; 106 } 107 for (int i=4;i<n;i++){ 108 for (int j=0;j<num;j++) 109 if (f[j].ok && dblcmp(p[i],f[j])>eps){ 110 dfs(i,j); 111 break; 112 } 113 } 114 int tmp=num; num=0; 115 for (int i=0;i<tmp;i++) if (f[i].ok) f[num++]=f[i]; 116 } 117 bool same(int s,int t){ 118 point3 &a=p[f[s].a],&b=p[f[s].b],&c=p[f[s].c]; 119 return fabs(volume(a,b,c,p[f[t].a]))<eps && fabs(volume(a,b,c,p[f[t].b]))<eps 120 && fabs(volume(a,b,c,p[f[t].c]))<eps; 121 } 122 //凸包上多边形面积 123 int polygon(){ 124 int res=0; 125 for (int i=0;i<num;i++){ 126 int flag=1; 127 for (int j=0;j<i;j++) 128 if (same(i,j)){flag=0;break;} 129 res+=flag; 130 } 131 return res; 132 } 133 }; 134 CH3D C; 135 int main(){ 136 int n; double x,y,z; 137 while (cin >> n){ 138 C.n=n; 139 for (int i=0;i<n;i++) cin >> C.p[i].x >> C.p[i].y >> C.p[i].z; 140 C.create(); 141 cout << C.polygon() << endl; 142 } 143 return 0; 144 }