【HDU3662】3D Convex Hull(三维凸包)

传送门


题解:

三维凸包板子题,所有面全部用三角形来记录,最后判断的时候去一下重就行了。


代码:

#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;}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值