101485 F

历史遗留问题
三维球面模板题叭算个。
有个性质挺好玩的。
飞机肯定是先飞一段陆地,再飞一段水,这样子。所以只有求一下所有交点按对起始点距离排序即可。
暂时还没理解两个弧线是怎么求交点的,抄的别人的板子。
好像我三维几何除了傻逼最小球覆盖这种其他的都没怎么写过。。。
教练模式真爽啊我草我要爽死了(bushi)

#include <bits/stdc++.h>
using namespace std;
typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
const db R=6370;
int sign(db k){
    if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}
struct P3{
    db x,y,z;
    P3 operator + (P3 k1){return (P3){x+k1.x,y+k1.y,z+k1.z};}
    P3 operator - (P3 k1){return (P3){x-k1.x,y-k1.y,z-k1.z};}
    P3 operator * (db k1){return (P3){x*k1,y*k1,z*k1};}
    P3 operator / (db k1){return (P3){x/k1,y/k1,z/k1};}
    db abs2(){return x*x+y*y+z*z;}
    db abs(){return sqrt(x*x+y*y+z*z);}
    P3 unit(){return (*this)/abs();}
    int operator < (const P3 k1) const{
        if (cmp(x,k1.x)!=0) return x<k1.x;
        if (cmp(y,k1.y)!=0) return y<k1.y;
        return cmp(z,k1.z)==-1;
    }
    int operator == (const P3 k1){
        return cmp(x,k1.x)==0&&cmp(y,k1.y)==0&&cmp(z,k1.z)==0;
    }
    void scan(){
        double k1,k2,k3; scanf("%lf%lf%lf",&k1,&k2,&k3);
        x=k1; y=k2; z=k3;
    }
};
P3 cross(P3 k1,P3 k2){return (P3){k1.y*k2.z-k1.z*k2.y,k1.z*k2.x-k1.x*k2.z,k1.x*k2.y-k1.y*k2.x};}
db dot(P3 k1,P3 k2){return k1.x*k2.x+k1.y*k2.y+k1.z*k2.z;}
db Acos(db x){return acos(max(-(db)1,min(x,(db)1)));}
// 球面距离 , 圆心原点 , 半径 1
db Odist(P3 a,P3 b){db r=Acos(dot(a,b)); return r;}
P3 getp(db x,db y){
    x=x*pi/180;y=y*pi/180;
    return P3{cos(x)*cos(y),cos(x)*sin(y),sin(x)};
}
bool checkSS(P3 a,P3 b,P3 c,P3 d,P3 &e){//from pku shanquan2
    e=cross(cross(a,b),cross(c,d));//弧线的交点
    if(sign(e.abs())==0)return 0;
    e=e.unit();
    if(cmp(Odist(a,e)+Odist(e,b),Odist(a,b))==0&&cmp(Odist(c,e)+Odist(e,d),Odist(c,d))==0)return 1;
    e=(P3){0,0,0}-e;
    if(cmp(Odist(a,e)+Odist(e,b),Odist(a,b))==0&&cmp(Odist(c,e)+Odist(e,d),Odist(c,d))==0)return 1;
    return 0;
}
P3 a[33][33],q[996];
int c,m,sz[33];db x,y;
int main(){
    scanf("%d",&c);
    for(int i=0;i<c;i++){
        scanf("%d",&sz[i]);
        for(int j=0;j<sz[i];j++){
            scanf("%lf%lf",&x,&y);
            a[i][j]=getp(x,y);
        }
    }
    scanf("%d",&m);
    db ans=0,s=0;P3 pre;
    bool f=0;
    for(int i=0;i<m;i++){
        scanf("%lf%lf",&x,&y);
        P3 ed = getp(x,y);
        if(i){
            ans+=Odist(pre,ed);
            q[0]=pre;int cnt=1;
            for(int i=0;i<c;i++)
                for(int j=0;j<sz[i];j++)
                    if(checkSS(pre,ed,a[i][j],a[i][(j+1)%sz[i]],q[cnt]))cnt++;
            q[cnt++]=ed;
            sort(q,q+cnt,[&](const P3& a,const P3& b){return Odist(pre,a)<Odist(pre,b);});
            for(int i=1;i<cnt;i++){ //一开始的一段一定在陆地上的
                if(f)s+=Odist(q[i],q[i-1]);
                if(i<cnt-1)f=!f;
            }
        }
        pre=ed;
    }
    printf("%.11f %.11f
",ans*R,s*100/ans);
    return 0;
}
原文地址:https://www.cnblogs.com/MXang/p/11286253.html