题目大意:
给定半径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|度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }