UVA_11817_TunnellingTheEarth

11817 - Tunnelling the Earth

Time limit: 1.000 seconds


There are different methods of transporting people from place
to place: cars, bikes, boats, trains, planes, etc. For very
long distances, people generally 
y in a plane. But this has
the disadvantage that the plane must 
y around the curved
surface of the earth. A distance travelled would be shorter
if the traveller followed a straight line from one point to the
other through a tunnel through the earth.
For example, travelling from Waterloo to Cairo requires a
distance of 9293521 metres following the great circle route
around the earth, but only 8491188 metres following the
straight line through the earth.
For this problem, assume that the earth is a perfect sphere
with radius of 6371009 metres.
Input
The rst line of input contains a single integer, the number of test cases to follow. Each test case is
one line containing four 
oating point numbers: the latitude and longitude of the origin of the trip,
followed by the latitude and longitude of the destination of the trip. All of these measurements are in
degrees. Positive numbers indicate North latitude and East longitude, while negative numbers indicate
South latitude and West longitude.
Output
For each test case, output a line containing a single integer, the difference in the distance between the
two points following the great circle route around the surface of the earth and following the straight
line through the earth, in metres. Round the difference of the distances to the nearest integer number
of metres.
Sample Input
1
43.466667 -80.516667 30.058056 31.228889
Sample Output
802333


这个问题就是告诉地球上两个点的经纬度

然后求这两点间的大弧长和绝对距离的差

实际上就是一个把球坐标转化成直角坐标的问题

然后利用向量夹角 解决球面距离 

之后与直线距离求差即可


#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

const double PI=acos(-1.0);
const double R=6371009;

inline double deg2rad(double deg)      //角度制换算弧度制
{
    return (deg*PI/180.0);
}
inline double rad2deg(double rad)      //弧度制换算角度制
{
    return (rad*180.0/PI);
}

struct Point
{
    double x,y,z;
    Point(){}
    Point(double a,double b,double c):x(a),y(b),z(c){}
    Point operator -(Point a)
    {
        return Point(x-a.x,y-a.y,z-a.z);
    }
};

double dot(Point a,Point b)
{
    return a.x*b.x+a.y*b.y+a.z*b.z;
}

int main()
{
    int t;
    double la1,lo1,la2,lo2;   //la纬度lo经度
    Point a,b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%lf%lf%lf",&la1,&lo1,&la2,&lo2);
        a.z=R*sin(deg2rad(la1));                  //转化成直角坐标
        a.x=R*cos(deg2rad(lo1))*cos(deg2rad(la1));
        a.y=R*sin(deg2rad(lo1))*cos(deg2rad(la1));
        b.z=R*sin(deg2rad(la2));
        b.x=R*cos(deg2rad(lo2))*cos(deg2rad(la2));
        b.y=R*sin(deg2rad(lo2))*cos(deg2rad(la2));
        //cout<<a.x<<" "<<a.y<<" "<<a.z<<endl;
        //cout<<b.x<<" "<<b.y<<" "<<b.z<<endl;
        double sita=acos(dot(a,b)/R/R);
        double ls=fabs(sita/(2*PI)*2*PI*R);
        double ll=fabs(sqrt(dot(a-b,a-b)));
        //cout<<ls<<" "<<ll<<endl;
        printf("%.0lf\n",ls-ll);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值