攜程第一場 第三題 攜程全球資料中心建設 (最小生成樹 經緯度距離)
阿新 • • 發佈:2019-01-30
今天沒有資格參賽,賽後群裡共享了一個比賽回放,怒水一發。
中文題,顯然的最小生成樹模型,就是求距離的時候有點糾結。
已知地球上兩點的經緯度,則兩點與球心的連線形成的夾角(圓心角)為:
arccos((sin緯度A×sin緯度B)+(cos緯度A×cos緯度B×cosAB兩地經度差絕對值)
#include <cstdio> #include <cstring> #include <cmath> const int INF=0x7fffffff; const double Pi=acos(-1.0); double farm[105][105],dis[105]; int n; bool visit[105]; double Prim () { int i,j,k; double temp=INF,ans=0; memset(visit,false,sizeof(visit)); for (i=1;i<=n;i++) dis[i]=farm[1][i]; //第一次判別 visit[1]=true; for (i=1;i<n;i++) { for (temp=INF,j=1;j<=n;j++) //找本輪最小 if (dis[j]<temp && visit[j]==false) temp=dis[k=j]; ans+=temp; visit[k]=true; //標記已找過的點 for (j=1;j<=n;j++) //下一輪 if (visit[j]==false && dis[j]>farm[k][j]) dis[j]=farm[k][j]; } return ans; } double x[105],y[105]; double Cal (int a,int b) { double tmp=sin(x[a]*Pi/180)*sin(x[b]*Pi/180); tmp+=cos(x[a]*Pi/180)*cos(x[b]*Pi/180)*cos(fabs(y[a]-y[b])*Pi/180); return acos(tmp); } int main () { int T,i; scanf("%d",&T); while (T--) { double D,L; scanf("%lf%lf%d",&D,&L,&n); D/=2; //半徑 memset(farm,0,sizeof(farm)); memset(dis,0,sizeof(dis)); for (i=1;i<=n;i++) { scanf("%lf%lf",&x[i],&y[i]); } for (i=1;i<=n;i++) for (int j=1;j<=n;j++) { farm[i][j]=D*Cal(i,j); } double ans=Prim(); if (ans>L) printf("N\n"); else printf("Y\n"); } return 0; }