在关键时候  总是一次又一次的失误在精度上面     在轻工业的校赛中 失误在读数  整整浪费了将近3个小时

 

题意相对来说比较简单   就是问三维的点到三维的一条线段的最短距离

一共四种可能

 点在线段上,距离为0;
 线段是一个点,用两点公式求;
三点构成直角三角形或者钝角三角形,那么直角或者钝角即为点到线段最近的点;
三点构成锐角三角形,那么距离为三角形的高,点到线段最近的点。
方法一:利用向量来求取夹角  从而判断那一点的位置
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<vector>
#include<math.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define N 100009
struct node
{
    double x,y,z;
}a[N];
double q(node a,node 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));
}
int xiang(node a,node b)
{
    return (a.x*b.x+a.y*b.y+a.z*b.z);
}
int main()
{
    int T,m;
    double x1,x2,y1,y2,nn;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lf%lf%lf%lf%lf",&nn,&x1,&y1,&x2,&y2);
        if(x1>x2)
        {
            swap(x1,x2);
            swap(y1,y2);
        }
        a[0].x=x1;a[0].y=y1;a[0].z=nn;
        a[1].x=x2;a[1].y=y2;a[1].z=nn;
        scanf("%lf%lf%lf",&a[2].x,&a[2].y,&a[2].z);
        scanf("%lf%lf%lf",&a[4].x,&a[4].y,&a[4].z);
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int n;
            scanf("%d",&n);
            a[5].x=a[2].x+n*a[4].x;
            a[5].y=a[2].y+n*a[4].y;
            a[5].z=a[2].z+n*a[4].z;///现在的三点为0 1 5
            a[6].x=a[5].x-a[0].x;a[6].y=a[5].y-a[0].y;a[6].z=a[5].z-a[0].z;///向量0 5
            a[7].x=a[5].x-a[1].x;a[7].y=a[5].y-a[1].y;a[7].z=a[5].z-a[1].z;///向量1 5
            a[8].x=a[0].x-a[1].x;a[8].y=a[0].y-a[1].y;a[8].z=a[0].z-a[1].z;///向量1 0
            a[9].x=-a[8].x;a[9].y=-a[8].y;a[9].z=-a[8].z;///向量0 1
            double e=q(a[0],a[5]);///0 5两点的长度
            double f=q(a[1],a[5]);///1 5两点的长度
            double g=q(a[0],a[1]);///0 1两点的长度
            double x=xiang(a[7],a[8]);///向量15与向量10的乘积
            double y=xiang(a[6],a[9]);///向量05与向量01的乘积
            double t;
            if(x<=0||y<=0)///乘积小于等于0即为在直角钝角三角形   直接找e与f最小值
                t=min(e,f);
            else///点5 在0 1上方
            {
                double cos1=1.0*x/(f*g);
                if(fabs(1-cos1)<1e-6)///避免在同一线段上
                    t=0;
                else
                    t=f*sin(acos(cos1));
            }
            printf("%.2f\n",t);
        }
    }
    return 0;
}

方法二:利用海伦公式  求高再使用勾股定理

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<vector>
#include<math.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define N 100009
struct node
{
    double x,y,z;
}a[N];
double q(node a,node 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));
}
int Q(node a,node b,node c)
{
    return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
int main()
{
    int T,m;
    double x1,x2,y1,y2,nn;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lf%lf%lf%lf%lf",&nn,&x1,&y1,&x2,&y2);
        if(x1>x2)///置换位置  让x1<x2  用于判断共线
        {
            swap(x1,x2);
            swap(y1,y2);
        }
        a[0].x=x1;a[0].y=y1;a[0].z=nn;
        a[1].x=x2;a[1].y=y2;a[1].z=nn;
        scanf("%lf%lf%lf",&a[2].x,&a[2].y,&a[2].z);
        scanf("%lf%lf%lf",&a[4].x,&a[4].y,&a[4].z);
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int n;
            scanf("%d",&n);
            a[5].x=a[2].x+n*a[4].x;///此刻的气球三维坐标
            a[5].y=a[2].y+n*a[4].y;
            a[5].z=a[2].z+n*a[4].z;
            if(a[0].x==a[1].x&&a[0].y==a[1].y)///判断飞船两端点是否同点
            {
                double gao=q(a[0],a[5]);
                printf("%.2f\n",gao);
                continue;
            }
            if(Q(a[5],a[0],a[1])==0)///利用叉积  判断三点是否共线
            {
                double b,c;
                if(a[5].x>=a[0].x&&a[5].x<=a[1].x)
                    b=0;
                else
                {
                    b=q(a[0],a[5]);
                    c=q(a[1],a[5]);
                    b=min(b,c);
                }
                printf("%.2f\n",b);
                continue;
            }
            double b=q(a[0],a[5]);///总体思想  利用面积求出高的长度  判断高是否在三点组成的三角形里面
            double c=q(a[1],a[5]);
            double d=q(a[0],a[1]);
            double ans=1.0*(b+c+d)/2;///利用海伦公式 求出来面积
            double mianji=sqrt(1.0*ans*(ans-d)*(ans-b)*(ans-c));
            double gao=mianji*2/d;///利用底边 求出高
            double sum=max(b,c);///与另外两边找到最大边
            double chang=sqrt(sum*sum-gao*gao);///勾股定理
            if(chang>=d)///如果所求高与最长边的第三边大于底边 证明高在三角形外
                b=min(b,c);
            else
                b=gao;
            printf("%.2f\n",b);
        }

    }
    return 0;
}

 

posted on 2017-04-17 16:21  云胡不喜。  阅读(259)  评论(0编辑  收藏  举报