其实就是一个数学问题,给你一个圆柱的底面的圆心以及底面圆心的两个点,然后求出这个圆的的法向量和这个圆的半径,这样的话就会得到n个圆半径以及n条直线(包括方向向量和直线上一点),再求这些直线的距离看是否小于等于两条直线所在的两个圆的半径之和,如果存在任何一组小于等于的话,就输出Lucky,否则输出最小差距;知道两条直线的法向量后,距离dis=|两条直线上两点的方向向量*(两条直线的方向向量的叉乘)| / |两条直线方向向量的模|#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; }
hdu 4619 Warm up 2
最新推荐文章于 2019-10-01 10:52:30 发布