传送门
题解:
直接建三维凸包,算点到平面的距离直接用六面体体积去除三角形面积就行了。
代码:
#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;}