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 } 
hdoj3662

相关文章: