POJ 2412 /// 空间几何 经纬度转三维坐标 角度转弧度 法向量

题目大意:

给定半径6378km的球上的 多个地点 及其  经纬度

多个询问 给定三个地点 A B C

A与B的等距点在球上形成一个大圆 

即球面上有一个到两点距离相等的大圆

且大圆所在平面垂直两点连线 

求C点到该大圆的最近球面距离 

1.特殊情况即A B为同一点 此时整个球面上的点都是等距点

则C到等距点的最近球面距离为0

2.设两点与球心组成一个平面S1 大圆与球面组成的平面S2

则S1与S2垂直 即两个平面相差90度

求出球心到C的向量cd与S1的夹角为ang度

则cd与S2的夹角则为|ang-90|度

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define mem(i,j) memset(i,j,sizeof(i))
#define inc(i,j,k) for(int i=j;i<=k;i++)
#define dec(i,j,k) for(int i=j;i>=k;i--)
const int N=1e5+5;
const double eps=1e-8;
const double PI=acos(-1.0);

int dcmp(double x) {
    if(abs(x)<eps) return 0;
    else return x<0 ? -1:1;
}
struct P {
    double x,y,z;
    P(){}
    P(double x,double y,double z):x(x),y(y),z(z){}
    P operator -(const P& p)const { return P(x-p.x,y-p.y,z-p.z); }
    double dot(const P& p) const { return x*p.x+y*p.y+z*p.z; }
    bool operator ==(const P& p)const {
        return dcmp(x-p.x)==0 && dcmp(y-p.y)==0 && dcmp(z-p.z)==0;
    }
}p[1005];
double Radian(double t) {
    return t*PI/180.0;
}
double lenP(P p) {
    return sqrt(p.dot(p));
}
double Angle(P a,P b) {
    return acos(a.dot(b)/lenP(a)/lenP(b));
}
int tot;
map<string,int>id;
double R=6378.0;

void ptf(string c,int res,string a,string b) {
    cout<<c<<" is ";
    if(res==-1) cout<<"?";
    else cout<<res;
    cout<<" km off "<<a<<"/"<<b<<" equidistance.
";
}

int main()
{
    ios::sync_with_stdio(false);
    id.clear(); tot=0;

    string s;
    double la,lo;
    while(cin>>s) {
        if(s=="#") break;
        id[s]=++tot;
        cin>>la>>lo;
        p[tot].x=R*cos(Radian(la))*sin(Radian(lo));
        p[tot].y=R*cos(Radian(la))*cos(Radian(lo));
        p[tot].z=R*sin(Radian(la));
    }

    string A,B,C;
    while(cin>>A) {
        if(A=="#") break;
        cin>>B>>C;

        int aid,bid,cid;
        bool flag=0;

        if(!id.count(A)) flag=1; else aid=id[A];
        if(!id.count(B)) flag=1; else bid=id[B];
        if(!id.count(C)) flag=1; else cid=id[C];

        double ans, ang;
        if(flag) ans=-1.0;
        else {
            P a=p[aid], b=p[bid], c=p[cid];
            if(a==b) ans=0.0;
            else {
                ang=Angle(a-b,c); 
                ang=abs(ang-PI/2.0); 
                ans=ang*R+0.5; // 弧长公式
            }
        } 
        ptf(C,(int)ans,A,B);
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zquzjx/p/10685011.html