• URAL 1988


    题意

    在一个星球(是一个球体)表面有一个飞机(坐标(x1,y1,z1),原点是星球中心),在空中有一个空间站(坐标(x2,y2,z2)),所有值均小于100,现在要使飞机与空间站相遇,飞机的速度是1,空间站速度是v,v是小于等于100的整数。飞机只能沿星球表面飞,而空间站可以任意飞,当然不能进入星球内部。

    【解答】

    首先可以把三维图形转化为二维的,也就是飞机,空间站,原点确定的那一个平面,

    为什么是含原点的平面?我们不妨把球体旋转一下,把飞机的初始位置固定在球体的最上边,空间站在球的侧边的上空,显然只有沿过原点平面的路线是最短的。

    现在能确定三个参量,飞机(设为点A)的高度p,空间站(设为点B)的高度q,以及飞机原点的直线,空间站原点的直线的夹角(角AOB)

    求夹角可以用点积 p*q = |p|*|q|*cos<p,q>

    注意用叉积=|p|*|q|*sin<p,q>是不推荐的,因为使用asin()函数求角度时,它不可能返回大于pi/2的角度(可以联系反三角函数图像),使用acos()则不会出现这种问题。【差错了三个小时发现是跪在了这里Σ(っ °Д °;)っ 】

    现在可以转化为二维图了

    我们不妨设空间站在x轴上,飞机在x轴上方,因为夹角一定小于180度,所以飞机在x轴上方或者下方是等价的。我们假设在x轴上方。

    这样成功转化为容易对其思考的二维图形

    下面就是如何选择相遇点的问题,假设相遇在第一个A1到C点之间,那么空间站一定是先沿圆的切线BC走,再沿弧CA1走,

    一开始想并不是沿弧走,而是沿折现走,比如说下边这个图

    沿ACE走,显然走ABDE更要近一些(三角形一边比另外两边和要短),以此类推,还是走弧最近。

    假设相遇点在A2处,那么空间站B就沿之间走到A2,飞船A就沿弧走到A2即可。

    寻找相遇点可以使用二分,但发现相遇点从A到D(圆与x轴正半轴交点),花费时间可能是先见减后增的,所以需要三分找时间最小值。

    三分的框架:

    while (l<r)
    {
        m1=l+(r-l)/3;
        m2=r-(r-l)/3;
        if(find(m1)<find(m2)) r=m2;
        else l=m1;
    }

    当然也可以二分时间,这样就可以避免三分了。

    程序代码:

    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <stdlib.h>
    #include <time.h>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<string>
    #include<algorithm>
    #include <limits.h>
    #include<cmath>
    #include<map>
    #include<queue>
    #include<set>
    using namespace std;
    
    typedef long long LL;
    int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
    bool flag;
    
    double ms,sp,fl,si,m1,m2,lenp,lenq,l,r,t1,t2;
    int v;
    struct node
    {
        double x,y,z;
    }p,q,s;
    
    double leng(node r)
    {
        return sqrt(r.x*r.x+r.y*r.y+r.z*r.z);
    }
    
    double sz(double x,double y)
    {
        return sqrt(x*x+y*y);
    }
    
    double getime(double m)
    {
        if (m<=ms)
        {
            sp=sz(lenp*sin(m),lenq-lenp*cos(m)) /v;
            fl=(si-m)*lenp;
            return max(sp,fl);
        }else
        {
            fl=(si-m)*lenp;
            sp=(sz(lenp*sin(ms),lenq-lenp*cos(ms)) + (m-ms)*lenp )/v;
            return max(fl,sp);
        }
    }
    
    int main()
    {
        scanf("%lf%lf%lf",&p.x,&p.y,&p.z);
        scanf("%lf%lf%lf",&q.x,&q.y,&q.z);
        scanf("%d",&v);
    
        s.x=p.x*q.x;
        s.y=p.y*q.y;
        s.z=p.z*q.z;
    
        lenp=leng(p);
        lenq=leng(q);
        si=acos((s.x+s.y+s.z)/lenp/lenq);
        ms=acos(lenp/lenq);
        l=0;
        r=si;
        while (r-l>=1e-10)
        {
            m1=(r+2*l)/3;
             m2=(2*r+l)/3;
             t1=getime(m1);
             t2=getime(m2);
    
            if (t1>t2) l=m1; else r=m2;
        }
    
        printf("%.6lf
    ",getime(l));
    
        return 0;
    }
  • 相关阅读:
    jq获取地址中的参数的值
    移动设备分辨率
    随机生成颜色
    小程序轮播图
    JavaScript中的constructor、instanceof、isPrototypeOf、typeof以及hasOwnProperty
    call()和apply()函数
    行内元素和块级元素
    js跳出循环的方法区别(break,continue,return)
    js 的四种设计模式的优缺点
    常见浏览器兼容性问题与解决方案
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4508644.html
Copyright © 2020-2023  润新知