1. 程式人生 > >攜程第一場 第三題 攜程全球資料中心建設 (最小生成樹 經緯度距離)

攜程第一場 第三題 攜程全球資料中心建設 (最小生成樹 經緯度距離)

今天沒有資格參賽,賽後群裡共享了一個比賽回放,怒水一發。

中文題,顯然的最小生成樹模型,就是求距離的時候有點糾結。

已知地球上兩點的經緯度,則兩點與球心的連線形成的夾角(圓心角)為:

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;
}