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; }