10316 - Airline Hub

题目:给出地球上的n个机场的经度和纬度,想在这里面确定一个HUB使得他到其他机场的最大距离最小。

分析:计算几何、大地坐标系。因为数据不大直接枚举即可,比较时利用圆心角可以提高计算效率,并控制精度。

            利用公式可直接解得两点的空间圆心角:acos(cos(lat1)*cos(lat2)*cos(lon1-lon2)+sin(lat1)*sin(lat2));

            因为又是大地坐标,所以再推一遍吧,推导过程如下:

                      

            如图,C,D为已知两点则有如下推导:            

            AB = r*cos(lat1);DE = r*cos(lat2);BE = r*sin(lat1) + r*sin(lat2);

            AD*AD = BE*BE + (AB-DE)*(AB-DE) = 2*r*r - 2*r*r*sin(lat1)*sin(lat2) - 2*r*r*cos(lat1)*cos(lat2);

            AC*AC = 2*AB*AB - 2*AB*AB*cos(lon1-lon2) = 2*r*r*cos(lat1)*cos(lat1)*(1-cos(lon1-lon2));

            DF*DF = 2*DE*DE - 2*DE*DE*cos(lon1-lon2) = 2*r*r*cos(lat2)*cos(lat2)*(1-cos(lon1-lon2));

            AC*DF = 2*r*r*cos(lat1)*cos(lat2)*(1-cos(lon1-lon2));

            由托勒密定理有 AC*DF + AD*AD = CD*CD 整理有:

            CD = r*sqrt(2-2*(cos(lat1)*cos(lat2)*cos(lon1-lon2)+sin(lat1)*sin(lat2)));

            设圆心角为α则:

            cos(0.5*α) = 0.5*CD/r = sqrt(0.5-0.5*(cos(lat1)*cos(lat2)*cos(lon1-lon2)+sin(lat1)*sin(lat2)));

            cos(0.5*α)*cos(0.5*α) = 0.5 - 0.5*(cos(lat1)*cos(lat2)*cos(lon1-lon2)+sin(lat1)*sin(lat2));

            cosα = 1 - 2*cos(0.5*α)*cos(0.5*α) = cos(lat1)*cos(lat2)*cos(lon1-lon2)+sin(lat1)*sin(lat2);

            圆心角为:acos(cos(lat1)*cos(lat2)*cos(lon1-lon2)+sin(lat1)*sin(lat2));

注意:精度控制。

  1. #include <iostream>  
  2. #include <cstdlib>  
  3. #include <cstdio>  
  4. #include <cmath>  
  5.   
  6. using namespace std;  
  7.   
  8. double dis[1005][1005];  
  9. double lat[1005];  
  10. double lon[1005];  
  11.   
  12. double dist( double l1, double d1, double l2, double d2 )  
  13. {  
  14.     double p = acos(-1.0);  
  15.     l1 *= p/180.0; d1 *= p/180.0;   
  16.     l2 *= p/180.0; d2 *= p/180.0;   
  17.     return acos(cos(l1)*cos(l2)*cos(d1-d2)+sin(l1)*sin(l2));  
  18. }  
  19.   
  20. int main()  
  21. {  
  22.     int n;  
  23.     while ( ~scanf("%d",&n) ) {  
  24.         for ( int i = 0 ; i < n ; ++ i )  
  25.             scanf("%lf%lf",&lat[i],&lon[i]);  
  26.           
  27.         for ( int i = 0 ; i < n ; ++ i )  
  28.         for ( int j = i ; j < n ; ++ j )  
  29.             dis[i][j] = dis[j][i] = dist( lat[i], lon[i], lat[j], lon[j] );  
  30.           
  31.         double min = 1e20;  
  32.         int    spa = 0;  
  33.         for ( int i = 0 ; i < n ; ++ i ) {  
  34.             double max = 0.0;  
  35.             for ( int j = 0 ; j < n ; ++ j )  
  36.                 if ( max+1e-6 < dis[i][j] )  
  37.                     max = dis[i][j];  
  38.             if ( min+1e-6 > max ) {  
  39.                 min = max;  
  40.                 spa = i;  
  41.             }  
  42.         }  
  43.           
  44.         printf("%.2lf %.2lf\n",lat[spa],lon[spa]);  
  45.     }  
  46.     return 0;  
  47. }  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值