链接:
Weapon
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 224 Accepted Submission(s): 178
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
Recommend
zhuyuanchen520
其实是盗版的KB大神的了。。。虽然他已经告诉了我是求异面直线的距离ORz kuangbin
题意:
博士发明了一种武器,武器的枪口是圆的,一旦点火,那么能量射线就会从圆的两端都出来
【这样就形成了底面圆确定,长度不限的圆柱体】
一旦有两个这样的能量圆柱体相遇【个人认为是包含了相切或者一个圆柱体包含了一个圆柱体的情况也算的,不过数据中没有】
那么就会发生爆炸,这样博士就能检测武器的威力了。
我认为只要不是第一种情况都应该可以输出 Lucky了
下面给出 T 组测试数据
每组测试数据包含了 N 个圆柱体
对于每一个圆柱体给出了它的底面圆的圆心坐标和底面圆圆周上的两个点
如果给出的圆所形成的圆柱体至少能有两个相遇,那么显然博士可以直接检测他们的威力,直接输出 Lucky
如果没有任何的圆柱体相遇,那么就求出所有的圆柱体中相邻最近的距离,也就是找最小的距离了。
算法:
异面直线距离 : 【百度百科】
思路:
把每一个圆面都与其它所有的圆面两两比较,看他们所形成的圆柱体是否有相交的
如何实现:求出圆柱体间的轴线间的距离与他们的半径比较就好了。
个人认为不用考虑轴线是否平行甚至共线的问题,应该是数据比较水了,怎么乱搞都过了Orz
code:
Accepted | 4617 | 15MS | 244K | 3486 B | C++ | free斩 |
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; const int maxn = 30+10; const double eps = 1e-10; int dcmp(double x) //精度 { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } struct Point3D{ double x; double y; double z; Point3D() {} Point3D(double _x, double _y, double _z){ x = _x; y = _y; z = _z; } Point3D operator -(const Point3D &b) const { return Point3D(x-b.x, y-b.y, z-b.z); } double operator *(const Point3D &b) const //点积 { return x*b.x+y*b.y+z*b.z; } Point3D operator ^(const Point3D &b) const //叉积 { return Point3D(y*b.z-z*b.y, z*b.x-x*b.z, x*b.y-y*b.x); } void input() { scanf("%lf%lf%lf", &x,&y,&z); } }; typedef Point3D Vector3D; struct Circle{ Point3D o, p1, p2; void input() { o.input(); p1.input(); p2.input(); } }circle[maxn]; double Length3D(Point3D p) //向量长度 { return sqrt(p*p); } //两异面直线距离【两直线上的点的连线在其法向量上的投影】 double cal(Point3D p1, Vector3D k1, Point3D p2, Vector3D k2) { Point3D nV = k1^k2; //normalVector return fabs(nV*(p1-p2)) / Length3D(nV); } int main() { int T; int n; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; i++) circle[i].input(); bool flag = false; double Min = 3000000; for(int i = 0; i < n && !flag; i++) { for(int j = i+1; j < n && !flag; j++) { Circle c1 = circle[i]; Circle c2 = circle[j]; double r1 = Length3D(c1.p1-c1.o); //圆半径 double r2 = Length3D(c2.p1-c2.o); Vector3D k1 = (c1.p1-c1.o)^(c1.p2-c1.o); //轴线的方向 Vector3D k2 = (c2.p1-c2.o)^(c2.p2-c2.o); double d = cal(c1.o, k1, c2.o, k2); //两异面直线距离 if(d <= r1+r2) //两圆相交或相切甚至内含应该都可以【题目不严谨没有相切和内含的数据】 { flag = true; break; } Min = min(Min, d-r1-r2); } } if(flag) printf("Lucky "); else if(dcmp(Min) <= 0) printf("Lucky "); else printf("%.2lf ", Min); } return 0; }