lightoj 1240 计算机图论(计算三维点到线段的距离)

来源:互联网 发布:java迭代器的使用 编辑:程序博客网 时间:2024/05/19 18:17

Description

Given a segment in 3D space, identified by A(x1, y1, z1), B(x2, y2, z2) and another point P(x, y, z) your task is to find the minimum possible Euclidean distance between the point P and the segment AB.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case starts with a line containing nine integers x1, y1, z1, x2, y2, z2, x, y, z. The magnitude of any integer will not be greater than 100.

Output

For each case, print the case number and the distance. Errors less than 10-6 will be ignored.

Sample Input

2

0 0 1 0 1 1 0 1 0

0 0 0 1 1 1 0 0 1

Sample Output

Case 1: 1

Case 2: 0.8164965809


   这个题目是一个几何问题,题目大意之灾三维空间中求一个点到一个线段的最短距离,我们可以采用向量点积的方法,首先设线段的端点为p1,p2,线段外的点是p,首先是计算向量p1-->p,  p1-->p2,的点积,如果两个数异号的话就说明p向线段做垂线垂足在线段外,所以最短距离为点到两个端点的最小值,如果两个同号的话就是求点到线段的垂线距离,我们可以将三个点连接起来,通过海伦公式求得三角形的面积,然后*2除底,就可以得到答案,但是还有一个重要的wa点就是要将数据类型全部转化为double进行运算,这样就可以减少int开方转化为double时候精度的损失(表示已经wa到哭);

代码如下:


#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>using namespace std;struct Point3D {            //三维点或矢量    double x, y, z;};struct Line3D {             // 三维的直线或线段    Point3D p1, p2;};double cross( Point3D &a,Point3D &b, Point3D &c){    return (a.x-c.x)*(b.x-c.x) + (a.y-c.y)*(b.y-c.y) +(a.z-c.z)*(b.z-c.z);}double dis(Point3D &a,Point3D &b){    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);}int main(){    //freopen("in.txt","r",stdin);    int T;    Point3D p,p1,p2;    scanf("%d",&T);    for(int i=1;i<=T;i++){  scanf("%lf %lf %lf %lf %lf %lf %lf %lf %lf",&p1.x,&p1.y,&p1.z,&p2.x,&p2.y,&p2.z,&p.x,&p.y,&p.z);  double d1 = dis(p,p1);  double d2 = dis(p,p2);  //cout << d1 << " " << d2 << endl;  double ans;  double c1 = cross(p,p1,p2);  double c2 = cross(p,p2,p1);  if ( c1 * c2 <= 0 )///判断垂足位置          ans = sqrt(double (min(d1,d2)));      else      {          double d3 = dis(p1,p2);          double s1 = sqrt(d1);          double s2 = sqrt(d2);          double s3 = sqrt(d3);          double c = (s1+s2+s3)/2;          double s = sqrt(c*(c-s1)*(c-s2)*(c-s3));///海伦公式          ans = 2*s/s3;      }      printf("Case %d: %.10lf\n",i,ans);}      return 0;}




0 0
原创粉丝点击