其实就是一个数学问题,给你一个圆柱的底面的圆心以及底面圆心的两个点,然后求出这个圆的的法向量和这个圆的半径,这样的话就会得到n个圆半径以及n条直线(包括方向向量和直线上一点),再求这些直线的距离看是否小于等于两条直线所在的两个圆的半径之和,如果存在任何一组小于等于的话,就输出Lucky,否则输出最小差距;
#include <cstdio>#include <cmath>double min(double x,double y){ return x>y?y:x;}struct node{ double x,y,z; double r,s,t; double R;};node v[35];void cal(double x1,double y1,double z1,double x2,double y2,double z2,int cur){ v[cur].r=y1*z2-y2*z1; v[cur].s=z1*x2-z2*x1; v[cur].t=x1*y2-x2*y1; v[cur].R=sqrt(x1*x1+y1*y1+z1*z1);}double solve(int cur,int pos){ double x,y,z; x=v[cur].x-v[pos].x; y=v[cur].y-v[pos].y; z=v[cur].z-v[pos].z; double r,s,t; r=v[cur].s*v[pos].t-v[cur].t*v[pos].s; s=v[cur].t*v[pos].r-v[cur].r*v[pos].t; t=v[cur].r*v[pos].s-v[cur].s*v[pos].r; return fabs(x*r+y*s+z*t)/sqrt(r*r+s*s+t*t);}int main(){ //freopen("in.txt","r",stdin); int t,n; scanf("%d",&t); while(t--) { double x1,y1,z1,x2,y2,z2; scanf("%d",&n); for(int i=0; i<n; ++i) { scanf("%lf%lf%lf",&v[i].x,&v[i].y,&v[i].z); scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&z1,&x2,&y2,&z2); cal(x1-v[i].x,y1-v[i].y,z1-v[i].z,x2-v[i].x,y2-v[i].y,z2-v[i].z,i); } double dis; int flag=-1; for(int i=0; i<n&&flag!=1; ++i) for(int j=i+1; j<n&&flag!=1; ++j) { double c; c=solve(i,j); if(c<=v[i].R+v[j].R) flag=1; if(flag==1) break; if(flag==-1) dis=c-(v[i].R+v[j].R),flag=0; else dis=min(dis,c-(v[i].R+v[j].R)); } if(flag==1) puts("Lucky"); else printf("%.2lf\n",dis); } return 0;}