1 /*
2 题意:给出n个weapon,每个weapon都是一个镭射光束,相当于一个无限长的实心圆柱,当两个weapon相接触,就会产生爆炸;
3 问给出n个weapon的某一垂直切面(为圆形),求这n个weapon之间是否会相接触,会则输出Lucky,否则输出两两之间weapon的最
4 短距离;
5
6 题解:计算几何:两直线的距离+平面法向量+直线与平面交点+平行线段
7 首先分别求出两个平面的法向量,因为圆柱的中心轴平行于平面法向量,然后求该向量与平面交点to,通过原点o与点to以及
8 圆柱的中心点center,将线段o-to平移到center-aim(aim为要求的点),这样center,aim两点就能表示中心轴线,最后求两直
9 线间的距离,最终减去两个半径即可得出最终答案。
10
11 注意:当给出的平面的center为原点时,需要特判,否则会出错
12 */
13 #include <cstdio>
14 #include <cmath>
15 #include <algorithm>
16
17 #define eps 1e-8
18 #define zero(x) (((x)>0?(x):-(x))<eps)
19
20 struct point3{double x,y,z;};
21 struct line3{point3 a,b;}linea,lineb;
22
23 //计算cross product U x V
24 point3 xmult(point3 u,point3 v){
25 point3 ret;
26 ret.x=u.y*v.z-v.y*u.z;
27 ret.y=u.z*v.x-u.x*v.z;
28 ret.z=u.x*v.y-u.y*v.x;
29 return ret;
30 }
31
32 //计算dot product U . V
33 double dmult(point3 u,point3 v){
34 return u.x*v.x+u.y*v.y+u.z*v.z;
35 }
36
37 //矢量差 U - V
38 point3 subt(point3 u,point3 v){
39 point3 ret;
40 ret.x=u.x-v.x;
41 ret.y=u.y-v.y;
42 ret.z=u.z-v.z;
43 return ret;
44 }
45
46 // 求平面法向量(原点到返回点即为所求向量)
47 point3 pvec(point3 s1,point3 s2,point3 s3)
48 {
49 return xmult(subt(s1,s2),subt(s2,s3));
50 }
51
52 //向量大小
53 double vlen(point3 p){
54 return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
55 }
56
57 // 两直线距离
58 double linetoline(point3 u1,point3 u2,point3 v1,point3 v2){
59 point3 n=xmult(subt(u1,u2),subt(v1,v2));
60 return fabs(dmult(subt(u1,v1),n))/vlen(n);
61 }
62
63 // 求直线与平面的交点
64 point3 intersection(point3 l1,point3 l2,point3 s1,point3 s2,point3 s3){
65 point3 ret=pvec(s1,s2,s3);
66 double t=(ret.x*(s1.x-l1.x)+ret.y*(s1.y-l1.y)+ret.z*(s1.z-l1.z))/
67 (ret.x*(l2.x-l1.x)+ret.y*(l2.y-l1.y)+ret.z*(l2.z-l1.z));
68 ret.x=l1.x+(l2.x-l1.x)*t;
69 ret.y=l1.y+(l2.y-l1.y)*t;
70 ret.z=l1.z+(l2.z-l1.z)*t;
71 return ret;
72 }
73
74
75 struct location
76 {
77 point3 a,b,o;
78 }s[29];
79
80 double getdistance(point3 a, point3 b)
81 {
82 return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + (a.z-b.z)*(a.z-b.z));
83 }
84
85
86 int main(void)
87 {
88 int t,n;
89 scanf("%d",&t);
90 while (t--)
91 {
92 scanf("%d",&n);
93 for(int i=0; i<n; i++)
94 {
95 scanf("%lf%lf%lf",&s[i].o.x, &s[i].o.y, &s[i].o.z);
96 scanf("%lf%lf%lf",&s[i].a.x, &s[i].a.y, &s[i].a.z);
97 scanf("%lf%lf%lf",&s[i].b.x, &s[i].b.y, &s[i].b.z);
98 }
99
100 double ans = 1e10;
101 bool flag = true;
102 for(int i=0; i<n-1; i++)
103 {
104 for(int j=i+1; j<n; j++)
105 {
106 point3 to1,to2,origin,tmp;
107 origin.x = origin.y = origin.z = 0;
108 to1 = pvec(s[i].a,s[i].o,s[i].b);
109 tmp = intersection(to1,origin,s[i].o,s[i].a,s[i].b);
110 // 特判该平面的center是否原点
111 if (!(zero(tmp.x-origin.x) && zero(tmp.y-origin.y) && zero(tmp.z-origin.z)))
112 {
113 to1.x = s[i].o.x - to1.x;
114 to1.y = s[i].o.y - to1.y;
115 to1.z = s[i].o.z - to1.z;
116 }
117
118 to2 = pvec(s[j].a,s[j].o,s[j].b);
119 tmp = intersection(to2,origin,s[j].o,s[j].a,s[j].b);
120 // 特判该平面的center是否原点
121 if (!(zero(tmp.x-origin.x) && zero(tmp.y-origin.y) && zero(tmp.z-origin.z)))
122 {
123 to2.x = s[j].o.x - to2.x;
124 to2.y = s[j].o.y - to2.y;
125 to2.z = s[j].o.z - to2.z;
126 }
127 double radis1 = getdistance(s[i].o,s[i].a);
128 double radis2 = getdistance(s[j].o,s[j].a);
129 double linedis = linetoline(s[i].o,to1,s[j].o,to2);
130 linedis = linedis - radis1 - radis2;
131 if (linedis < eps)
132 {
133 flag = false;
134 break;
135 }
136 ans = std::min(ans,linedis);
137 }
138 if (!flag)
139 break;
140 }
141 if (flag)
142 printf("%.2lf\n",ans);
143 else
144 printf("Lucky\n");
145
146 }
147 return 0;
148 }