医院选址问题
[问题描述]
有一个乡镇,共有n个村庄,现在要建立一家医院, 那么医院应该选址在哪个村庄合适呢?设计算法,满足如下选址要求:使得所有村庄到达医院都最近。
[基本要求]
(1) 随机生成一个有n个村庄和村庄间的路径及路径长度,并输出;
(2) 显示出各村庄到医院的路径和路径长度。
算法思想:
1、将图中各顶点代表村庄,顶点之间的连线代表村庄之间的路径。由此交通图就转化成了有限顶点和有限条边组成的无向图,图中顶点之间的关系用权值表示。
2、求最佳选址通常有两种思路:一是求最小路径总和最小,这种情况通常适用于物流中心等情况,主要考虑的是运输成本最小;二是求距离最远的顶点顶点最近(最小偏心度),此情况适用于消防站等情况,主要考虑的是其他顶点的时间(距离)公平。由于就医是较紧急的事件,所以需要以所有患者都能尽快就医为出发点,这样医院选址问题就转化成了求所有顶点之间的最短距离的最大值中最小值问题。因此需要求出每一对顶点之间的距离,用弗洛伊德算法比较方便。
求最佳选址通常有两种思路:一是求最小路径总和最小,这种情况通常适用于物流中心等情况,主要考虑的是运输成本最小;二是求距离最远的顶点最近,此情况适用于消防站等情况,主要考虑的是其他顶点的时间(距离)公平。
源代码:
head.h
#pragma once //保证头文件不会被编译多次
#include<iostream>
#include<ctime>
using namespace std;
#define OK 1 //定义ok=1,函数结果状态代码
#define MAXINT 32767 //极大值(无路径)
#define MAXLEG 100 //有路径的路径长度的极大值
#define MVNUM 10 //最大顶点数
typedef int Status; //Status为函数返回值类型,其值是函数结果状态代码
typedef int VerTexType; //声明顶点数据类型为整型
typedef int ArcType; //声明边的权值类型为整型
typedef int Patharc[MVNUM][MVNUM]; //最短路径上顶点vi的后一顶点的序号P[v][w](矩阵存储)
typedef int ShortPathTable[MVNUM][MVNUM]; //记录vi到vj之间的最短路径长度D[v][w](矩阵存储输出)
static int z[MVNUM]; //定义一维数组,初始化为-1,记录医院所在村庄(因为可能不止一个) (int z[MVNUM] error:一个或多个多重定义的符号) 不能在头文件.h里面定义全局变量,那样编译的时候两个cpp文件都会包含头文件里面定义的变量而冲突找到;由于静态全局变量的作用域限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其他源文件中引起错误。
typedef struct //图的邻接矩阵存储表示
{
VerTexType vexs[MVNUM]; //顶点表(村庄)
ArcType arcs[MVNUM][MVNUM]; //邻接矩阵(每个村庄之间的路径长度)
int vexnum; //图当前的顶点数
int arcnum; //图当前的边数
}AMGraph;
void initialize(); //初始化一维数组,用于记录医院选址
Status CreateUDN(AMGraph& G); //创建任意无向网
void PrintMatrix(AMGraph G); //输出邻接矩阵
void ShortestPath_Floyd(AMGraph G, Patharc P, ShortPathTable D); //弗洛伊德算法求每一对顶点的最短路径
void PrintShortPath(AMGraph G, Patharc P, ShortPathTable D); //打印最短路径
void Algorithm(AMGraph G, Patharc P, ShortPathTable D); //求出最小偏心度,并输出医院选址
void PrintHospital(AMGraph G, Patharc P, ShortPathTable D); //打印各村庄到医院的路径
//#pragma warning(disable:6385) 微软在默认情况下强制对C和C++代码强制使用SAL分析,在此处属于误报
//#pragma warning(disable:6386)
function.cpp
#include"head.h"
void initialize() //初始化z[]
{
for (int i = 0; i < MVNUM; i++)
{
z[i] = -1;
}
}
Status CreateUDN(AMGraph& G) //采用邻接矩阵表示法创建无向网G
{
srand((unsigned)time(NULL)); //用系统时间来初始化种子
int v1, v2; //邻接矩阵的arcs[][]
int w, i, j, k, r;
int n = rand() % 6 + 1; //随机生成村庄个数n(1<=n<=6)
cout << "随机生成该乡镇的村庄个数n:" << n << endl;
G.vexnum = n; //顶点数为n
//根据顶点数进行边数的赋值
if (G.vexnum == 1