岛国问题

原创 2014年12月03日 13:01:38

【问题描述】一家互联网服务商(简称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) );
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

一片看懂肠道菌群在人体中的作用-岛国科普又走在了我们前面

影片信息日文名:腸内フローラ解明!驚異の細菌パワー 中文名:肠道细菌 / 肠道花园 类型:医療健康 时长:49min 官网:http://www.nhk.or.jp/special/detai...

【全球机器人排名榜】第一名来自岛国日本,怎么破?

机器人是自动执行工作的机器装置,它既可以接受人类指挥,又可以运行预先编排的程序,也可以根据以人工智能技术制定的原则纲领行动。它的任务是协助或取代人类的工作,例如生产业、建筑业,或是危险的工作。 ...
  • bzgkzlw
  • bzgkzlw
  • 2017年07月13日 17:14
  • 163

o.boj 1034 冥王星的故事II-占领岛国

注:最近这一系列ACM的内容,都是2年多之前的代码,自己回顾一下。 冥王星的故事II-占领岛国   Submit: 1193   Accepted:362 Time Limit: 2000M...
  • wenlele
  • wenlele
  • 2011年12月17日 09:40
  • 794

说说下载岛国动作片那点事儿

最近在搞网络,当然在这过程中它也搞了我。 最近,项目中需要导出电信、联通、移动这几个ISP的网段,就写了下面的脚本。 先来了典型的shell脚本,单线程版 OPERATOR_TMP=...

360云盘岛国云盘资源共享吧你懂的

360云盘岛国云盘资源共享吧你懂的  H色---罓---址---观看入口→→██ωωω `787cc` C σm ██ 岛国1000部精品,你懂得深夜福利,上资源文件共享群-360云盘岁月静然,时光老...

Java经典问题算法大全

  • 2017年12月11日 16:31
  • 2.06MB
  • 下载

算法java实现--回溯法--0-1背包问题

0-1背包问题的java实现(回溯法) 具体问题描述以及C/C++实现参见网址 http://blog.csdn.net/liufeng_king/article/details/8764319...

各种函数零点问题的处理

  • 2017年12月10日 10:41
  • 1019KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:岛国问题
举报原因:
原因补充:

(最多只允许输入30个字)