CodingTrip - 携程编程大赛 (预赛第一场)


携程全球数据中心建设

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 725    Accepted Submission(s): 307


Problem Description
  
  
携程为了扩展全球在线旅游业务,决定在全球建设多数据中心,以便提高网站的访问速度和容灾处理。 为了实现每个数据中心的数据能互通,数据中心之间需要通过光纤连接。为了节约光纤成本,我们计划采用点对点方式来达到最终各个数据中心的数据互通,每个数据中心本身都可以作为数据中转站。做为全球多数据中心设计者,您需要知道最短的光纤总长度,来把所有的数据中心都实现互通。假设地球是个圆球,且表面是平滑的,并且没有任何阻碍物(河流,山脉)。 输入数据是一组数据中心的经纬度 纬度: -90° 到 +90° 经度: -180° 到 +180° (圆周率pi= 3.14159265358979323846)
 

Input
  
  
第一行第一个整数N(1≤N≤100),表示有多少个用例. 每个用例包含了: 第一行,小数D(1≤D≤1,000,000),表面圆球的直径(公里). 第二行,小数L(1≤L≤1,000,000) 光纤总长度 (公里). 第三行,整数C(1≤C≤100) ,表示数据中心的数量. 接下来的C行, 每行有2个形如"X Y"的小数,表示每个数据中心的纬度(-90≤X≤90)和经度 (-180≤Y≤180).
 

Output
  
  
每个用例输出一行. 如果光纤长度L足够连接所有数据中心,输出"Y", 否则输出"N"。
 

Sample Input
  
  
2 12742 5900 3 51.3 0 42.5 -75 48.8 3 12742 620 2 30.266 97.75 30.45 91.1333
 

Sample Output
  
  
Y N

给你 C个地球上的点,给你他们的经纬度 , 求一下他们的MST,检验是否在 给定的限制长度内。

把这个题目记录下来 主要是因为  自己半天没有推算出来 给定两点的 经纬度 和地球半径 求两点间的弧的长度或者 夹角 的 公式。。就在网上找了下。。

剩下的就是最小生成树的 套用了。

CODE:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
using namespace std;
#define INF 1000000000
#define PI acos(-1.0)
#define N 105
int n,c,ss,par[N];
double d,l;
struct node
{
	double x,y;
	int id;
}point[N];
struct no
{
	int u,v;
	double w;
}edge[N*N];
int cmp(no a,no b)
{
	return a.w<b.w;
}
int fi(int x)
{
	if(x!=par[x]) par[x]=fi(par[x]);
	return par[x];
}
double rad(double x)
{
	return x*PI/180.0;
}
double kru()
{
	double ret=0;
	int cou=0;
	for(int i=1;i<=ss;i++)
	{
		int u=edge[i].u;
		int v=edge[i].v;
		int x=fi(u);
		int y=fi(v);
		if(x!=y)
		{
			par[y]=x;
			cou++;
			ret+=edge[i].w;
			if(cou>=c-1) return ret;
		}
	}
	return INF;
}
double get_dis(double x1,double y1,double x2,double y2)
{
	double radx1=rad(x1);
	double radx2=rad(x2);
	double a=radx1-radx2;
	double b=rad(y1)-rad(y2);
	double ret=2*asin(sqrt(sin(a/2)*sin(a/2) + cos(radx1)*cos(radx2)*sin(b/2)*sin(b/2)));
	return d*ret/2.0;
}
int main()
{
	scanf("%d",&n);
	while(n--)
	{
		scanf("%lf",&d);
		scanf("%lf",&l);
		scanf("%d",&c);
		for(int i=1;i<=c;i++)
		{
			scanf("%lf%lf",&point[i].x,&point[i].y);
			point[i].id=i;
		}
		ss=0;
		for(int i=0;i<=c;i++) par[i]=i;
		for(int i=1;i<=c;i++)
		{
			for(int j=i+1;j<=c;j++)
			{
				double tmp=get_dis(point[i].x,point[i].y,point[j].x,point[j].y);
				edge[++ss].w=tmp;
				edge[ss].u=i; edge[ss].v=j;
			}
		}
		sort(edge+1,edge+1+ss,cmp);
		double ans=kru();
		if(ans<=l) puts("Y");
		else puts("N");
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值