zoukankan      html  css  js  c++  java
  • 2017轻工业校赛 tmk射气球 简单的数学题 https://acm.zzuli.edu.cn/zzuliacm/problem.php?id=2127

    在关键时候  总是一次又一次的失误在精度上面     在轻工业的校赛中 失误在读数  整整浪费了将近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
    ",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
    ",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
    ",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
    ",b);
            }
    
        }
        return 0;
    }
  • 相关阅读:
    C++ CheckListBox
    TreeView查获节点并选中节点
    创建文件自动重命名
    bat
    Edit显示行号
    FindStringExact
    Extended ComboBox添加图标
    C++ Combobox输入时自动完成
    C++ ComboBox基础
    C++ Code_combobox
  • 原文地址:https://www.cnblogs.com/a719525932/p/6723484.html
Copyright © 2011-2022 走看看