传送门
题解:
三维凸包板子题,所有面全部用三角形来记录,最后判断的时候去一下重就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define db double
#define cs const
using std::cerr;
using std::cout;
cs int N=3e2+7;
cs double eps=1e-8;
int sign(double x){
return x<-eps?-1:(x>eps?1:0);
}
struct Pnt{
db x,y,z;Pnt(){}Pnt(cs db _x,cs db _y,cs db _z):x(_x),y(_y),z(_z){}
friend Pnt operator+(cs Pnt &a,cs Pnt &b){return Pnt(a.x+b.x,a.y+b.y,a.z+b.z);}
friend Pnt operator-(cs Pnt &a,cs Pnt &b){return Pnt(a.x-b.x,a.y-b.y,a.z-b.z);}
friend Pnt operator*(cs Pnt &a,cs Pnt &b){return Pnt(a.y*b.z-b.y*a.z,a.z*b.x-b.z*a.x,a.x*b.y-b.x*a.y);}
friend db dot(cs Pnt &a,cs Pnt &b){return a.x*b.x+a.y*b.y+a.z*b.z;}
friend bool operator==(cs Pnt &a,cs Pnt &b){return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps&&fabs(a.z-b.z)<eps;}
friend bool operator!=(cs Pnt &a,cs Pnt &b){return !(a==b);}
inline db len()cs{return sqrt(x*x+y*y+z*z);}
};
int n,ct,id[N][N];
bool ok[N<<1|1];
Pnt p[N];
inline db area(cs Pnt &a,cs Pnt &b,cs Pnt &c){
return ((b-a)*(c-a)).len();
}
inline db volume(cs Pnt &a,cs Pnt &b,cs Pnt &c,cs Pnt &d){
return dot((b-a)*(c-a),d-a);
}
struct Face{
int a,b,c;Face(){}Face(int _a,int _b,int _c):a(_a),b(_b),c(_c){}
Pnt normal()cs{return (p[b]-p[a])*(p[c]-p[a]);}
db area()cs{return normal().len();}
db volume(cs Pnt &d)cs{return ::volume(p[a],p[b],p[c],d);}
}f[N<<1|1];
inline db see(cs Pnt &a,cs Face &f){return f.volume(a);}
inline bool same(cs Face &f1,cs Face &f2){
return !sign(f1.volume(p[f2.a]))&&!sign(f1.volume(p[f2.b]))&&!sign(f1.volume(p[f2.c]));
}
void deal(int x,int a,int b);
void dfs(int x,int a);
void deal(int x,int a,int b){
if(ok[id[a][b]]){
if(see(p[x],f[id[a][b]])>eps)dfs(x,id[a][b]);
else {
id[x][b]=id[a][x]=id[b][a]=++ct;
ok[ct]=true;f[ct]=Face(x,b,a);
}
}
}
void dfs(int p,int x){
ok[x]=false;
deal(p,f[x].b,f[x].a);
deal(p,f[x].c,f[x].b);
deal(p,f[x].a,f[x].c);
}
void Convex_3D(){
ct=0;bool flag=true;
for(int re i=2;i<=n;++i)if(p[1]!=p[i])
{std::swap(p[2],p[i]);flag=false;break;}
if(flag)return;flag=true;
for(int re i=3;i<=n;++i)if(sign(area(p[1],p[2],p[i])))
{std::swap(p[3],p[i]);flag=false;break;}
if(flag)return ;flag=true;
for(int re i=4;i<=n;++i)if(sign(volume(p[1],p[2],p[3],p[i])))
{std::swap(p[4],p[i]);flag=false;break;}
if(flag)return ;flag=true;
for(int re i=1;i<=4;++i){
int a=(i&3)+1,b=(a&3)+1,c=(b&3)+1;
if(see(p[i],Face(a,b,c))>0)std::swap(b,c);
id[a][b]=id[b][c]=id[c][a]=++ct;
f[ct]=Face(a,b,c);ok[ct]=true;
}
for(int re i=5;i<=n;++i){
for(int re j=1;j<=ct;++j)
if(ok[j]&&see(p[i],f[j])>eps)
{dfs(i,j);flag=false;break;}
if(flag)continue;flag=true;int cur=0;
for(int re j=1;j<=ct;++j)if(ok[j]){
if((++cur)==j)continue;f[cur]=f[j];ok[cur]=true;
id[f[cur].a][f[cur].b]=id[f[cur].b][f[cur].c]=id[f[cur].c][f[cur].a]=cur;
}ct=cur;
}
}
void Main(){
while(~scanf("%d",&n)){
for(int re i=1;i<=n;++i)
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
Convex_3D();int res=0;
for(int re i=1;i<=ct;++i){
bool flag=true;for(int re j=1;j<i;++j)
if(same(f[i],f[j])){flag=false;break;}
res+=flag;
}std::cout<<res<<"\n";
}
}
void file(){
#ifdef zxyoi
freopen("convex3D.in","r",stdin);
#endif
}
signed main(){file();Main();return 0;}