hdu 4617
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4617
题目大意:给你n个无限长的圆柱,问你能否碰到,能的话,输出 “Lucky” ,不能的话,输出最小的距离。
思路:裸计算几何。比赛的时候叉积是记得,但是两直线的最短距离公式忘了,赛后百度了一下,就A掉了。。 这题应该很基础了吧,连我这种没学过计算几何的人都能很快A掉。。= =
以前没怎么做过计算几何,木有什么模板,函数什么都是手写的。。
代码如下:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct Point
{
double x,y,z;
Point(){}
Point(double a,double b,double c) : x (a),y(b),z(c){}
} cnt;
struct Ho
{
Point cen,a,b;
Point line;
double r;
} ho[33];
Point cal_xl(Point a,Point b)
{
cnt.x = a.x-b.x;
cnt.y = a.y-b.y;
cnt.z = a.z-b.z;
return cnt;
}
Point cal_cj(Point a,Point b)
{
return Point(a.y*b.z-b.y*a.z , b.x*a.z-a.x*b.z , a.x*b.y-b.x*a.y);
}
double cal_dis(Point a,Point b)
{
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));
}
double mod(Point a)
{
return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
}
double dc(Point a,Point b)
{
return fabs(a.x*b.x+a.y*b.y+a.z*b.z);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
double a,b,c;
for(int i=0;i<n;i++)
{
for(int j=0;j<3;j++)
{
scanf("%lf%lf%lf",&a,&b,&c);
if(j==0) ho[i].cen = Point(a,b,c);
else if(j==1) ho[i].a = Point(a,b,c);
else ho[i].b = Point(a,b,c);
}
}
for(int i = 0;i<n;i++)
{
ho[i].line = cal_cj(cal_xl(ho[i].cen,ho[i].a),cal_xl(ho[i].cen,ho[i].b));
ho[i].r = cal_dis(ho[i].a,ho[i].cen);
}
int ok=0;
double minn = 1e9;
for(int i=0;i<n&&!ok;i++)
{
for(int j = i+1;j<n;j++)
{
Point n = cal_cj(ho[i].line,ho[j].line);
double k = dc(n ,cal_xl(ho[i].cen,ho[j].cen))/mod(n);
if(k<=ho[i].r+ho[j].r)
{
ok=1;
break;
}
else
{
minn = min(minn,k-ho[i].r-ho[j].r);
}
}
}
if(ok) puts("Lucky");
else printf("%.2f\n",minn);
}
return 0;
}