岛国问题

【问题描述】一家互联网服务商(简称PIN)在太平洋上发现了几座新岛屿,其中最大的一个岛(称为主岛)已经连接到Internet,但是其他岛和主岛之间没有光缆连接,所以无法上网。为了让所有岛上的居民都能上网,每个岛和主岛之间都必须有直接或者间接的光缆连接。
       每条实线表示一根光缆,它的长度等于两个岛屿中心位置(路由器位置)的几何距离,图上的数字是该岛上的居民数量。为了节省成本,所有光缆的总长度尽量小。  


       岛屿之间的光缆同时开始铺设,以每天一公里的速度铺设,那么较短的路径肯定先铺设完,某岛屿只要与主岛之间存在一条已经铺设好的电缆,就能接入互联网。PIN非常关注所有居民的平均接入互联网的时间,假设第 i 个岛屿的居民人数是mi ,接入互联网需要的时间是ti ,则平均接入时间是:

 


【输入形式】输入内容包括所有岛屿的信息。第一行是岛屿的个数nn< 50);接下来共有n行,每一行包括三个正整数:xi  yi  mi ,中间空格隔开,(xi , yi )是岛屿的位置坐标,坐标轴单位是公里,mi 是该岛屿的居民人数。输入的第一个岛屿是主岛。
【输出形式】输出所有居民的平均接入互联网的平均天数,结果保留两位小数。
【样例输入】

7
11 12 2500
14 17 1500
9 9 750
7 15 600
19 16 500
8 18 400
15 21 250
【样例输出】3.20
【样例说明】不用考虑岛屿之间具有相同距离的情况
【评分标准】该题目由2002年的ACM/ICP World Final改编而成,作为选做题


分析:

本题可用之前分析的Prim最小生成树来生成路径,之后的关键就是在找到这些边的时候记录下这些边,并算出需要等待的时间。

需要等待的时间——

若岛A直接连接到主岛,则A岛需要等待的时间就是二者的距离

假设A通过B连接到主岛,

如果A到B的边长小于B到主岛的边长,则A岛等的时间实际上是B到主岛的时间

否则如果A到B的边长大于B到主岛的边长,则A岛等的时间是A岛修光缆到B岛的时间

#include<stdio.h>
#include<string.h>
#include<math.h>

#define INF 0xfffffff							// infinity
#define MAXSIZE 20

int n;
int people[MAXSIZE], point[MAXSIZE][2];			//point[]记录点的坐标位置
double edge[MAXSIZE][MAXSIZE], time[MAXSIZE];	//因为每天铺一公里,所以time[]其实就是距离

void Prim(double edge[][MAXSIZE], int u);
double distance(int a, int b, int c, int d);

int main()
{
	int i, j;
	int sum_people = 0;
	double sum_time = 0;

	memset(edge, 0, sizeof(edge));				// void * memset (void * p,int c,size_t n)
	scanf("%d", &n);
	for(i = 1; i <= n; i++)						//读点的坐标和人数
		scanf("%d%d%d", &point[i][0], &point[i][1], &people[i]);

    for(i = 1; i <= n; i++)						//计算总人数
        sum_people += people[i];

	for(i = 1; i <= n; i++)						// 构造邻接矩阵
		for(j = 1; j <= n; j++)
			edge[i][j] = edge[j][i] = distance(point[i][0], point[i][1], point[j][0], point[j][1]);

	Prim(edge, 1);						//Prim算法,从主岛(顶点1)开始

	for(i=2; i<=n; i++)					//计算所有人等待的总时间(主岛除外),故i=2
		sum_time += time[i] * people[i];

	printf("%.2f\n", sum_time / sum_people);
	return 0;
}

void Prim(double edge[][MAXSIZE], int u)
{
	int nearvex[MAXSIZE] = {0};
	double lowcost[MAXSIZE] = {0}, mincost = INF * 1.0;
	int i, j;
	int v = -1;
	double weight = 0;

	for(i=1; i<=n; i++)							//NO.1 对距离进行初始化
	{
		lowcost[i] = edge[u][i];
		nearvex[i] = u;
	}
	lowcost[u] = 0;
	nearvex[u] = -1;

	for(i=1; i<n; i++)					//NO.4 循环n-1次,加入n-1个顶点
	{
        mincost = INF;		// very important!!!!! EVERY TIME mincost should be initialized to find the minimum
		for(j=1; j<=n; j++)				//NO.3 更新距离,找到边的权值最小的那个点
			if(nearvex[j] != -1 && lowcost[j] < mincost)
			{
				mincost = lowcost[j];
				v = j;				//记录下这个边的权值最小的点
			}

		if(v != -1)					//如果找到那个点,进行NO.2
		{
	//		printf("%d--(%f)-->%d\n", nearvex[v], lowcost[v], v);   //打印加入的流程
//****************************************************************************************************************
//相对于最小生成树的关键代码:
			if(nearvex[v] == u)				//若毗邻主岛,直接将时间(距离)更新为边长
				time[v] = lowcost[v];
			else if(lowcost[v] <= time[ nearvex[v] ])
				time[v] = time[ nearvex[v] ];
				else
					time[v] = lowcost[v];
//假设A通过B连接到主岛,如果A到B的边长小于B到主岛的边长,则A岛等的时间实际上是B到主岛的时间
//否则如果A到B的边长大于B到主岛的边长,则A岛等的时间是A岛修光缆到B岛的时间
//****************************************************************************************************************

			nearvex[v] = -1;					//将点加入T2
			weight += lowcost[v];

			for(j=1; j<=n; j++)					//加入后,对距离进行更新
			{
				if(nearvex[j] != -1 && edge[v][j] < lowcost[j])
				{
					lowcost[j] = edge[v][j];
					nearvex[j] = v;
				}
			}
		}
	}
}

double distance(int a, int b, int c, int d)
{
	return sqrt( (a-c)*(a-c) + (b-d)*(b-d) );
}


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
马耳他是一个太阳能可再生能源的活跃国家。由于地理位置特殊,太阳能在这个岛国的能源转型中占据了重要地位。 首先,太阳能作为一种清洁的可再生能源,在马耳他发电方面扮演着重要角色。大量的太阳能电池板被广泛安装于建筑物屋顶、工厂设施等区域,利用阳光转化为电能供应给当地居民和企业使用。这种方式提供了可持续的电力资源,减少了对化石燃料的依赖,降低了马耳他的碳排放量。 其次,太阳能在马耳他的水热供暖方面也发挥了重要作用。许多家庭和商业建筑已经安装了太阳能热水器,利用太阳能加热水供应给居民和商户。这种方式不仅减少了对传统电力和燃气的依赖,还节约了能源成本和减少了环境影响。 此外,太阳能在马耳他的旅游业中也起到了积极的作用。马耳他是一个地中海岛国,拥有丰富的阳光资源。许多酒店和度假村已经开始利用太阳能发电来提供可持续、清洁的能源供应。这种举措加强了马耳他旅游业的可持续发展,为游客提供了更环保和可负担的住宿选择。 总之,马耳他太阳能的应用已经取得了显著的成果。从发电到供暖再到旅游业,太阳能在马耳他的转型中扮演着重要角色,减少了对传统能源的依赖,促进了可持续发展。然而,还需进一步推广太阳能技术,并继续加大对清洁能源的投资,以实现更可持续的未来。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值