[图] 医院选址问题 - 最短路径Floyd应用 - C语言实现

版权声明:本文为博主原创文章,若有错误之处望大家批评指正!转载需附上原文链接,谢谢! https://blog.csdn.net/summer_dew/article/details/83993817

【问题背景】

已知有向图的邻接矩阵如下图所示,需在其中一个结点建立医院
	要求:
		1. 该结点距其他各个结点的最长往返路径最短
		2. 相同条件下总的往返路程越短越好
	矩阵:
		0	13	∞	4	∞
		13	0	15	∞	5
		∞	∞	0	12	∞
		4	∞	12	0	∞
		∞	∞	6	3	0

【思路】

最长往返路径
		1. 该矩阵是一个有向图,也就是说A->B的路径,可能并不是B->A的路径
		2. 最长往返路径= A->B的路径长度 + B->A的路径长度
	思路:最短路径的应用问题
		1. 求出任意两点之间的最短路径长度
		2. 遍历每一个结点,计算该结点到其余结点的最长往返路径max,总的SUM
		3. 取出max最小的,即为医院的地址
			其中,max相同的话,看sum,sum最小的为医院的地址
	使用算法:
		常用的最短路径算法有Dijkstra与Floyd
		1. Dijkstra常用与一个结点到其余各点的最短路径的情景
		2. Floyd常用与求任意两点的最短路径
		这里我们选Floyd更方便

【结果】
在这里插入图片描述

【代码】

#include<stdio.h>
#include<stdlib.h>

#define MAX 10
#define INF 10e6

typedef struct mgraph{
	char vers[MAX];
	int arcs[MAX][MAX];
	int vernum,arcnum;
}MGraph;

void InitMGraph(MGraph *pM);	//初始化图
int** GetPathValueMatrixByFloyd(MGraph G);	//得到最短路径矩阵
int GetHospitalIndex(MGraph G, int **pathvalues); //计算最优医院地址

/*测试数据
5
15
ABCDE
0 13 1000000 4 1000000
13 0 15 1000000 5
1000000 1000000 0 12 1000000
4 1000000 12 0 1000000
1000000 1000000 6 3 0
*/
int main() {
	MGraph G;
	int i,j;
	int **pathvalues;

	InitMGraph(&G);
	pathvalues = GetPathValueMatrixByFloyd(G);
	// debug
//	for (i=0; i<G.vernum; i++) {
//		for (j=0; j<G.vernum; j++) {
//			printf("%d\t", pathvalues[i][j]);
//		}
//		printf("\n");
//	}
	i = GetHospitalIndex(G, pathvalues);
	printf("\n推荐医院地址:%c\n", G.vers[i]);

	return 0;
}

void InitMGraph(MGraph *pM) {
	int i,j;

	scanf("%d", &pM->vernum);
	scanf("%d", &pM->arcnum);
	scanf("%s", &pM->vers);
	for (i=0; i<pM->vernum; i++) {
		for (j=0; j<pM->vernum; j++) {
			scanf("%d", &pM->arcs[i][j]);
		}
	}
}

int** GetPathValueMatrixByFloyd(MGraph G) {
	int **pathvalue; //路径值矩阵
	int i,j,v;

	// 创建最短路径的路径值矩阵
	pathvalue = (int **)malloc(sizeof(int)*G.vernum);
	for (i=0; i<G.vernum; i++) {
		pathvalue[i] = (int *)malloc(sizeof(int)*G.vernum);
	}
	// 初始化路径值矩阵与路径矩阵
	for (i=0; i<G.vernum; i++) {
		for (j=0; j<G.vernum; j++) {
			pathvalue[i][j] = G.arcs[i][j];
		}
	}
	// 开始遍历每个结点,把该结点当成中间点,路径会不会更短
	for (v=0; v<G.vernum; v++) {
		for (i=0; i<G.vernum; i++) {
			if (v==i) continue;
			for (j=0; j<G.vernum; j++) {
				if (v==j) continue;
				if (pathvalue[i][j] > pathvalue[i][v] + pathvalue[v][j]) { //v为中心点,更小
					pathvalue[i][j] = pathvalue[i][v] +pathvalue[v][j]; //更新值
				}
			}
		}
	}

	return pathvalue;
}

int GetHospitalIndex(MGraph G, int **pathvalues) {
	int hosp,hospMin,hospSum;
	int v,max,sum;
	int w;
	int goBackValue;

	hosp=-1; //还未选
	// 在v建立医院,算出max与sum
	for (v=0; v<G.vernum; v++) {
		max = -1; //还未有最大值
		sum = 0;  //往返值的和
		// 到其余各点
		for (w=0; w<G.vernum; w++) {
			if (v==w) continue;
			goBackValue = pathvalues[v][w] + pathvalues[w][v]; //往返值
			sum += goBackValue;
			if (max == -1) { //还没有最大值
				max = goBackValue;
			} else if (goBackValue > max) { //v->w的往返值更大
				max = goBackValue;
			}
		}
		
		if (hosp==-1) { // 还没有最优值
			hosp = v;
			hospMin = max;
			hospSum = sum;
		} else {		// 有最优值
			// 当前的结点v更优
			if (hospMin > max || (hospMin==max && hospSum>sum)) {
				hosp = v;
				hospMin = max;
				hospSum = sum;
			}
		}
	}

	return hosp;
}

猜你喜欢

转载自blog.csdn.net/summer_dew/article/details/83993817