【郑轻邀请赛 A】tmk射气球

【题目链接】:https://acm.zzuli.edu.cn/zzuliacm/problem.php?id=2127

【题意】

【题解】

把气球和飞艇所代表的直线投影到xoy面上
设气球所在位置为A(x3,y3)
飞艇所在的直线段的两个端点B(x2,y2),C(x1,y1);
设经过B且垂直BC的直线为l1,经过C且垂直BC的直线为l2;
则如果A在l1和l2所围的范围内;
则最短距离为点到直线的距离(只不过变成3维的了);
如果不在
则最短距离为
A到B和A到C之间的距离的较小者.
点到直线的距离可以根据直角边列个方程算出来
(相当于在一个三角形里面求一条边上的高);

【Number Of WA

0

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define rep1(i,x,y) for (int i = x;i <= y;i++)
#define LL long long

LL h,xx1,yy1,xx2,yy2,xx,yy,zz,XX,YY,ZZ;

LL sqr(LL x) {return x*x;}

double dis(LL x1,LL y1,LL z1,LL x2,LL y2,LL z2)
{
    return sqrt(sqr(x1-x2)+sqr(y1-y2)+sqr(z1-z2));
}

bool in(LL x1,LL y1,LL x2,LL y2,LL x3,LL y3)
{
    return (x3-x1)*(x2-x1)+(y3-y1)*(y2-y1)>0 && (x1-x2)*(x3-x2)+(y1-y2)*(y3-y2)>0;
}

int main()
{
    //freopen("D:\rush.txt","r",stdin);
    int T;
    cin >> T;
    while (T--)
    {
        cin >> h >> xx1 >> yy1 >> xx2 >> yy2;
        cin >> xx >> yy >> zz >> XX >> YY >> ZZ;
        int n;
        cin >> n;
        rep1(i,1,n)
        {
            LL t;
            cin >> t;
            LL xx3,yy3,zz3;
            xx3 = xx+XX*t,yy3 = yy+YY*t,zz3 = zz+ZZ*t;
            if (xx1==xx2 && yy1==yy2)
            {
                cout << fixed << setprecision(2) << dis(xx1,yy1,h,xx3,yy3,zz3)<<endl;
                continue;
            }
            double a = dis(xx1,yy1,h,xx3,yy3,zz3),b = dis(xx2,yy2,h,xx3,yy3,zz3);
            double c = dis(xx1,yy1,h,xx2,yy2,h);
            if (in(xx1,yy1,xx2,yy2,xx3,yy3))
            {
                double dd = (a*a+c*c-b*b)/(2.0*c);
                double ans= sqrt(a*a-dd*dd);
                cout << fixed << setprecision(2) << ans <<endl;
            }
            else
            {
                cout << fixed << setprecision(2) << min(a,b) <<endl;
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626420.html