Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 266 Accepted Submission(s): 208
算法:
题目意思:
D博士发明了一个新武器,要对它进行威力测试。可以威力测试的条件是圆形炮筒两端发出的射线构成无限长的圆柱,若有两个圆柱相交后相切,则可以测试,输出“Lucky”否则输出圆柱间的最短距离。
算法思想:
计算几何问题,将圆柱的中轴线为参考线,利用空间两条直线的距离公式
|AB*n|/|n|,AB代表两条中轴线的两点构成的向量,这里是两个圆的圆心连线形成的向量。
n代表法线向量,即公垂线所在的向量。n向量可以通过两圆的垂线的叉积得到。
AB*n为AB与n的内积。
代码:
#include <iostream> #include <cstdio> #include <cmath> using namespace std; struct node { double x,y,z; double a_x,a_y,a_z; double b_x,b_y,b_z; double n_x,n_y,n_z; double r; } Cir[40]; double fa_x,fa_y,fa_z,AB_x,AB_y,AB_z; const double MAX=1e9; double getDist(node A,node B) { double len_fa,len_she; //法向量 fa_x=A.n_y*B.n_z-A.n_z*B.n_y; fa_y=-A.n_x*B.n_z+A.n_z*B.n_x; fa_z=A.n_x*B.n_y-A.n_y*B.n_x; len_fa=sqrt(fa_x*fa_x+fa_y*fa_y+fa_z*fa_z); //AB向量 AB_x=A.x-B.x; AB_y=A.y-B.y; AB_z=A.z-B.z; len_she=fabs(AB_x*fa_x+AB_y*fa_y+AB_z*fa_z); return len_she/len_fa; } int main() { int t,n,i; cin>>t; while(t--) { cin>>n; for(i=0;i<n;++i) { cin>>Cir[i].x>>Cir[i].y>>Cir[i].z; cin>>Cir[i].a_x>>Cir[i].a_y>>Cir[i].a_z; cin>>Cir[i].b_x>>Cir[i].b_y>>Cir[i].b_z; Cir[i].n_x=(Cir[i].a_y-Cir[i].y)*(Cir[i].b_z-Cir[i].z)-(Cir[i].a_z-Cir[i].z)*(Cir[i].b_y-Cir[i].y); Cir[i].n_y=-(Cir[i].a_x-Cir[i].x)*(Cir[i].b_z-Cir[i].z)+(Cir[i].a_z-Cir[i].z)*(Cir[i].b_x-Cir[i].x); Cir[i].n_z=(Cir[i].a_x-Cir[i].x)*(Cir[i].b_y-Cir[i].y)-(Cir[i].a_y-Cir[i].y)*(Cir[i].b_x-Cir[i].x); //计算圆柱的半径 Cir[i].r=sqrt((Cir[i].x-Cir[i].a_x)*(Cir[i].x-Cir[i].a_x)+(Cir[i].y-Cir[i].a_y)*(Cir[i].y-Cir[i].a_y)+(Cir[i].z-Cir[i].a_z)*(Cir[i].z-Cir[i].a_z)); } int flag=1,j; double dist,ans=MAX; //遍历 for(i=0;i<n-1 && flag;++i) { for(j=i+1;j<n;++j) { dist=getDist(Cir[i],Cir[j]);//计算两个圆柱的距离 //cout<<dist-(Cir[i].r+Cir[j].r)<<endl; ans=min(dist-(Cir[i].r+Cir[j].r),ans); if(ans<=0) { flag=0; break; } } } if(flag) { printf("%.2lf\n",ans); } else { cout<<"Lucky"<<endl; } } return 0; }