比赛
题目
题意:给出空间中n个圆,院由圆心和圆上两点确定,且三点不共线,圆可以往两面延伸形成无限长的圆柱。问是否有圆柱相交,如果不相交,输出最短距离。
解法:用叉积求出所有圆柱轴线,然后计算直线间的距离是否大于两个圆柱半径之和来判断。听说可以用纯数学的方法,但我不会。
//time:15MS //memory:288K #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <iostream> using namespace std; const double EPS = 1e-8; const int MAXN = 505; int dcmp(double x) { if(fabs(x)<EPS) return 0; return x<0? -1:1; } struct Point3{ double x,y,z; Point3(){} Point3(double a,double b,double c):x(a),y(b),z(c){} Point3 operator+(const Point3 &a)const { return Point3(x+a.x,y+a.y,z+a.z); } Point3 operator-(const Point3 &a)const { return Point3(x-a.x,y-a.y,z-a.z); } Point3 operator*(double c)const { return Point3(x*c,y*c,z*c); } void input(){scanf("%lf%lf%lf",&x,&y,&z);} void output(){printf("%lf %lf %lf",x,y,z);} }; typedef Point3 Vector3; struct Line{ Point3 a,b; double r; }; Vector3 Cross(Vector3 a,Vector3 b) { return Vector3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x); } double Dot(Vector3 a,Vector3 b) { return a.x*b.x+a.y*b.y+a.z*b.z; } double Length(Vector3 a) { return sqrt(Dot(a,a)); } double Distoplane(Point3 p, Point3 p0, Vector3 n) { return fabs(Dot(p-p0,n)/Length(n)); } double Distoline(Point3 p, Point3 a, Point3 b) { Vector3 v1 = b-a,v2 = p-a; return Length(Cross(v1,v2))/Length(v1); } double Dislinetoline(Point3 a, Point3 b, Point3 c, Point3 d) { Vector3 n = Cross(a-b,c-d); if(dcmp(Length(n))==0) return Distoline(b,c,d); else return Distoplane(a,c,n); } int main() { //freopen("/home/qitaishui/code/in.txt","r",stdin); int cas,n; Line l[35]; Point3 a,b,c; Vector3 v; scanf("%d",&cas); while(cas--) { scanf("%d",&n); for(int i = 0; i < n; i++) { a.input(),b.input(),c.input(); l[i].r = Length(a-b); l[i].a = a; v = Cross(b-a,c-a); l[i].b = a+v; } bool flag = 1; double ans = 1e300,tmp; for(int i = 0; i < n&&flag; i++) for(int j = i+1; j < n&&flag; j++) { tmp = Dislinetoline(l[i].a,l[i].b,l[j].a,l[j].b); //cout<<tmp<<" "<<l[i].r+l[j].r<<endl; if(dcmp(tmp-l[i].r-l[j].r)<=0) flag = 0; else ans = min(ans,tmp-l[i].r-l[j].r); } if(!flag) printf("Lucky\n"); else printf("%.2f\n",ans); } return 0; }