HDU 4617

题目多读几次就明白了。主要是求异面直线的距离,然后用距离和两圆半径之和作比较。

空间直线的距离d=|AB*n| / |n| (AB表示异面直线任意2点的连线,n表示法向量,法向量为两条异面直线方向向量的叉积,|n|表示模。

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int MAXN=50;
const double eps=1e-8;
struct point {
	double x,y,z;
};
struct line {
	point a,b;
	double r;
};
int n;
point tmp[3]; line le[MAXN];
point vectical;

point operator - (const point &a, const point &b){  //减法 
	point t;
	t.x=a.x-b.x; t.y=a.y-b.y; t.z=a.z-b.z;
	return t;
}
point operator ^ (const point &u, const point &v){  //叉乘 
	point t;
	t.x=u.y*v.z-v.y*u.z; t.y=u.z*v.x-u.x*v.z; t.z=u.x*v.y-u.y*v.x;
	return t; 
}

point operator + (const point &a, const point &b){
	point t;
	t.x=a.x+b.x; t.y=a.y+b.y; t.z=a.z+b.z;
	return t;
}

double operator *(const point &a, const point &b){
	return a.x*b.x+a.y*b.y+a.z*b.z;
}

double dist(point &a, point &b){
	double tx=a.x-b.x; double ty=a.y-b.y; double tz=a.z-b.z;
	return sqrt(tx*tx+ty*ty+tz*tz);
}

double len (point &t){
	return sqrt(t.x*t.x+t.y*t.y+t.z*t.z);
}

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			for(int j=0;j<3;j++)
			scanf("%lf%lf%lf",&tmp[j].x,&tmp[j].y,&tmp[j].z);
			le[i].a=tmp[0];
			vectical=(tmp[1]-tmp[0])^(tmp[2]-tmp[0]);
			le[i].b=le[i].a+vectical;
			le[i].r=dist(tmp[1],tmp[0]);
		}
		bool flag=false;
		double ans=1e10;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				if(i!=j){
					vectical=(le[i].a-le[i].b)^(le[j].a-le[j].b);
					point tt=le[i].a-le[j].a;
					double dd=fabs((tt*vectical))/len(vectical);
					if(dd<=le[i].r+le[j].r){
						flag=true;
						break;
					}
					else ans=min(ans,dd-le[i].r-le[j].r);
				}
			}
			if(flag)break;
		}
		if(flag) printf("Lucky\n");
		else printf("%.2lf\n",ans);
	}
	return 0;
}

  

posted @ 2014-08-08 21:54  chenjunjie1994  阅读(204)  评论(0编辑  收藏  举报