【HDU4266】The Worm in the Apple(三维凸包)

传送门


题解:

直接建三维凸包,算点到平面的距离直接用六面体体积去除三角形面积就行了。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define db double
#define cs const

using std::cerr;
using std::cout;

cs db eps=1e-8;

int sign(db x){return x<-eps?-1:(x>eps?1:0);}

struct Pnt{
	db x,y,z;Pnt(){}Pnt(db _x,db _y,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 !sign(a.x-b.x)&&!sign(a.y-b.y)&&!sign(a.z-b.z);}
	friend bool operator!=(cs Pnt &a,cs Pnt &b){return !(a==b);}
	inline db len()cs{return sqrt(x*x+y*y+z*z);}
};

db area(cs Pnt &a,cs Pnt &b,cs Pnt &c){
	return ((b-a)*(c-a)).len();
}
db vol(cs Pnt &a,cs Pnt &b,cs Pnt &c,cs Pnt &d){
	return dot((b-a)*(c-a),d-a);
}

cs int N=1e3+7;

int n,ct,id[N][N];
bool ok[N<<1|1];

Pnt p[N];

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 vol(cs Pnt &d)cs{return dot(normal(),d-p[a]);}
}f[N<<1|1];

db dist(cs Face &f,cs Pnt &p){
	return fabs(f.vol(p))/f.area();
}

void dfs(int,int);
void deal(int,int,int);

void deal(int x,int a,int b){
	if(ok[id[a][b]]){
		if(f[id[a][b]].vol(p[x])>eps)dfs(x,id[a][b]);
		else {
			id[b][a]=id[a][x]=id[x][b]=++ct;
			ok[ct]=true,f[ct]=Face(b,a,x);
		}
	}
}

void dfs(int p,int x){
	ok[x]=false;
	deal(p,f[x].b,f[x].a);
	deal(p,f[x].a,f[x].c);
	deal(p,f[x].c,f[x].b);
}

void Convex_3D(){
	ct=0;bool flag=true;
	for(int re i=2;i<=n;++i)if(p[i]!=p[1])
	{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(vol(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(Face(a,b,c).vol(p[i])>0)std::swap(b,c);
		id[a][b]=id[b][c]=id[c][a]=++ct;
		ok[ct]=true;f[ct]=Face(a,b,c);
	}
	for(int re i=5;i<=n;++i){
		for(int re j=1;j<=ct;++j)
			if(f[j].vol(p[i])>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)&&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 m;scanf("%d",&m);
		while(m--){
			Pnt q;scanf("%lf%lf%lf",&q.x,&q.y,&q.z);
			db ans=1e20;for(int re i=1;i<=ct;++i)ans=std::min(ans,dist(f[i],q));
			printf("%.4f\n",ans);
		}
	}
}

void file(){
#ifdef zxyoi
	freopen("worm.in","r",stdin);
#endif
}
signed main(){file();Main();return 0;}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值