Weapon Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 279 Accepted Submission(s): 220 Problem Description Doctor D. are researching for a horrific weapon. The muzzle of the weapon is a circle. When it fires, rays form a cylinder that runs through the circle verticality in both side. If one cylinder of rays touch another, there will be an horrific explosion. Originally, all circles can rotate easily. But for some unknown reasons they can not rotate any more. If these weapon can also make an explosion, then Doctor D. is lucky that he can also test the power of the weapon. If not, he would try to make an explosion by other means. One way is to find a medium to connect two cylinder. But he need to know the minimum length of medium he will prepare. When the medium connect the surface of the two cylinder, it may make an explosion. Input The first line contains an integer T, indicating the number of testcases. For each testcase, the first line contains one integer N(1 < N < 30), the number of weapons. Each of the next 3N lines  contains three float numbers. Every 3 lines represent one weapon. The first line represents the coordinates of center of the circle, and the second line and the third line represent two points in the circle which surrounds the center. It is supposed that these three points are not in one straight line. All float numbers are between -1000000 to 1000000. Output For each testcase, if there are two cylinder can touch each other, then output 'Lucky', otherwise output then minimum distance of any two cylinders, rounded to two decimals, where distance of two cylinders is the minimum distance of any two point in the surface of two cylinders. Sample Input 3 3 0 0 0 1 0 0 0 0 1 5 2 2 5 3 2 5 2 3 10 22 -2 11 22 -1 11 22 -3 3 0 0 0 1 0 1.5 1 0 -1.5 112 115 109 114 112 110 109 114 111 -110 -121 -130 -115 -129 -140 -104 -114 -119.801961 3 0 0 0 1 0 1.5 1 0 -1.5 112 115 109 114 112 110 109 114 111 -110 -121 -130 -120 -137 -150 -98 -107 -109.603922 Sample Output Lucky 2.32 Lucky Source 2013 Multi-University Training Contest 2 沒啥技巧吧,就是直接算 思路:對於每一個圓柱,算出它的中心軸方向向量同時保存圓心坐標,算出兩個直線之間的距離d,如果距離大於兩個圓柱的半徑之和那就記錄mind=d-rr[i]-rr[j],否則就輸出Lucky。兩直線平行時距離好算,不平行時有點麻煩,用向量的叉乘來計算。
#include<stdio.h> #include<math.h> double r[31][3],center[31][3],rr[31]; int main() { double x1,x2,x3,y1,y2,y3,z1,z2,z3,r1,r2,r3,mind,temp,temp1; double a1,b1,c1,a2,b2,c2; int t,n,m,i,j,k,flag; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;i++) { scanf("%lf%lf%lf",&x1,&y1,&z1); scanf("%lf%lf%lf",&x2,&y2,&z2); scanf("%lf%lf%lf",&x3,&y3,&z3); center[i][0]=x1; center[i][1]=y1; center[i][2]=z1; rr[i]=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)); a1=x2-x1; b1=y2-y1; c1=z2-z1; a2=x3-x1; b2=y3-y1; c2=z3-z1; r1=b1*c2-b2*c1; r2=a2*c1-a1*c2; r3=a1*b2-a2*b1; r[i][0]=r1; r[i][1]=r2; r[i][2]=r3; //printf("%.4f %.4f %.4f %.4f\n",rr[i],r1,r2,r3); } mind=1000000000; flag=1; for(i=0;i<n-1&&flag;i++) { for(j=i+1;j<n;j++) { a1=r[i][0]; b1=r[i][1]; c1=r[i][2]; a2=r[j][0]; b2=r[j][1]; c2=r[j][2]; r1=b1*c2-b2*c1;//垂直 r2=a2*c1-a1*c2; r3=a1*b2-a2*b1; //printf("%d %d %.4f %.4f %.4f\n",i,j,r1,r2,r3); if(!(r1==0&&r2==0&&r3==0))//兩直線不平行 { temp=fabs(((center[i][0]-center[j][0])*r1+(center[i][1]-center[j][1])*r2+(center[i][2]-center[j][2])*r3)/sqrt(r1*r1+r2*r2+r3*r3));//利用 if(temp<=rr[i]+rr[j]) { printf("Lucky\n"); flag=0; break; } else if(mind>temp-(rr[i]+rr[j])) mind=temp-rr[i]-rr[j]; //printf("%.2f\n",temp); } else //平行 { a2=center[i][0]-center[j][0],b2=center[i][1]-center[j][1],c2=center[i][2]-center[j][2]; temp1=sqrt(((b1*c2-b2*c1)*(b1*c2-b2*c1)+(a2*c1-a1*c2)*(a2*c1-a1*c2)+(a1*b2-b1*a2)*(a1*b2-b1*a2))/(a1*a1+b1*b1+c1*c1)); if(temp1<=rr[i]+rr[j]) { printf("Lucky\n"); flag=0; break; } else if(mind>temp1-rr[i]-rr[j]) mind=temp1-rr[i]-rr[j]; } } } if(flag) printf("%.2f\n",mind); } return 0; }