您的位置:首页 > 其它

【hdoj 4617】Weapon

2015-08-09 13:12 281 查看
Weapon

Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)

Total Submission(s): 407 Accepted Submission(s): 325

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

题意理解:每次有多组测试数据,每组数据有n个圆,为无限长圆柱体的横截面,接下来的3n行代表每个圆的圆心以及圆上的两点的坐标。如果任意两个圆柱有交点则输出Lucky,否则输出圆柱之间的最短距离。

解题思路:纯数学题,求异面直线的距离。将任意两个圆所在的平面的法向量求出来,最后只需判断这两条直线之间的距离与两个圆柱的半径之和的大小。

异面直线距离公式:

,s1,s2是两条直线的方向向量,M,N是两条直线上的任意一点。

当两个异面直线所在的平面平行的时候,不能用向量积,可画图得出公式为d=|s1XMN|/|s1|

向量积:s1xs2=|s1|*|s2|sinp

code:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
double  nv[31][3],r[31],ct[31][3];
int main()
{
int T;
int n,flag;
double ans,temp,x1,x2,x3,y1,y2,y3,z1,z2,z3;
double a1,a2,a3,b1,b2,b3,c1,c2,c3;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int 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);
ct[i][0]=x1;
ct[i][1]=y1;
ct[i][2]=z1;
r[i]=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
nv[i][0]=(y2-y1)*(z3-z1)-(y3-y1)*(z2-z1);//第i个圆的法向量
nv[i][1]=(x3-x1)*(z2-z1)-(x2-x1)*(z3-z1);
nv[i][2]=(x2-x1)*(y3-y1)-(x3-x1)*(y2-y1);
}
ans=1000000000;
flag=1;
for(int i=0;i<n-1&&flag;i++)
{
for(int j=i+1;j<n;j++)
{
a1=nv[i][0];
b1=nv[i][1];
c1=nv[i][2];
a2=nv[j][0];
b2=nv[j][1];
c2=nv[j][2];
a3=b1*c2-b2*c1;//两个向量x乘以后的向量
b3=a2*c1-a1*c2;
c3=a1*b2-a2*b1;
if(!(a3==0&&b3==0&&c3==0))
{
temp=fabs(((ct[i][0]-ct[j][0])*a3+(ct[i][1]-ct[j][1])*b3+(ct[i][2]-ct[j][2])*c3)/sqrt(a3*a3+b3*b3+c3*c3));
if(temp<=r[i]+r[j])
{
printf("Lucky\n");
flag=0;
break;
}
else
ans=min(ans,(temp-r[i]-r[j]));
}
else   //两个向量平行的情况
{
a2=ct[i][0]-ct[j][0];
b2=ct[i][1]-ct[j][1];
c2=ct[i][2]-ct[j][2];
a3=b1*c2-b2*c1;
b3=a2*c1-a1*c2;
c3=a1*b2-a2*b1;
temp=sqrt((a3*a3+b3*b3+c3*c3)/(a1*a1+b1*b1+c1*c1));
if(temp<=r[i]+r[j])
{
printf("Lucky\n");
flag=0;
break;
}
else
ans=min(ans,(temp-r[i]-r[j]));
}
}
}
if(flag)
printf("%.2f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: