2019年12月份的课程设计。
问题描述:
n个村庄之间的路径用有向加权图表示,要从这n个村庄中选择一个村庄建立一所医院,问这所医院应建在哪个村庄,能使所有的村庄都离这家医院最近(能使离医院最远的村庄到医院最近)或能使所有的村庄到达医院的距离之和达到最小。
我的思路是:
A. 首先是,随机生成了村庄的数量,定义结构变量,通过调用GreateUDN函数给顶点表赋值,随机生成村庄之间的路径长度并存放在邻接矩阵中,即二维数组arcs中,创建完成后调用show函数把村庄间的路径长度的邻接矩阵展示输出,横纵方向显示村庄号码,方便用户直观看出村庄间的路径长度。
B. 因为问题是医院如何选址,因此我先假设医院建在各个村庄,每一次假设,军调用ShortsetPath_DIJ(狄杰特斯拉算法)函数,求出被假设村庄到各个村庄的最短路径,并用一维数组sum记录其到各个村庄的最短路径之和,方便后续比较选择最小者,以最小的那个元素的下标为村庄号码的村庄便是修建医院的最佳地址,可符合题目要求。
C. 选择好修建医院的村庄后,便需要展示各个村庄到医院的最短路径所经过的村庄路程以及各个村庄到医院的最短路径。此时调用shoeshort函数输出展示路径过程,调用ShortsetPath_DIJ3函数输出各个村庄到医院的最短路径长度(此处仅输出单个村庄到医院的最短路径),循环调用输出过程以及最短路径长度。
D. 期间,编程时注意代码输出格式规整、直观问题。具体结果展示详见结果截图,
以下是完整代码,注释比较详细了,若有问题,欢迎指正!
#include<iomanip> //用到间隔输出:setw(int)
#include "time.h" //用到时间函数
#include "math.h" // 用到随机函数
#include<iostream>
using namespace std;
#define MaxInt 32767 //表示极大值,即无穷∞
#define MVNum 30 //最大顶点数
typedef int Status; //1成功 0失败
typedef int VerTexType; //顶点的数据类型为 int型 即,此处以 0,1,2,3,4...表示村庄
typedef int ArcType; //边的权值类型为整型 路径长度为整型
typedef struct
{
VerTexType vexs[MVNum]; //顶点表 存放顶点信息
ArcType arcs[MVNum][MVNum]; //邻接矩阵 存放权值,即路径长度
int vexnum; //图当前顶点数 在mian函数中随机生成顶点数,传值到GreateUDN函数构造有向网
int arcnum; //图当前边数 构建完全有向图,根据随机生成的顶点数计算边数
}AMGragh;
bool S[MVNum]; //记录从源点v0到终点vi是否已被确定最短路径长度,1表示确定,0表示尚未确定
int Path[MVNum][MVNum]; // 记录从源点v0到终点vi的当前最短路径上vi的直接前驱顶点序号。
int D[MVNum]; //记录从源点v0到终点vi的当前最短路径长度
int sum[30]; //每个元素都记录着一个村庄到其余各个村庄之间的最短路径之和
Status GreateUDN(AMGragh &G,int m) //采用邻接矩阵表示法创建有向网G
{
G.vexnum = m; //m为main函数中随机生成的一个整型数据 当作顶点数
cout << "村庄总个数: " << G.vexnum << endl;
G.arcnum = m * (m - 1) / 2; //此处假设村庄以及其路径构成的图为:有向完全图
cout << "村庄之间路径条数 " << G.arcnum << endl;
for (int i = 0; i < G.vexnum; ++i)
{
//vexs[MVNum]为顶点表,顶点数据类型是整型,村庄用整形数据表示,共有m个,vex[0]-vexs[m-1]存入村庄0 -(m-1)
G.vexs[i]=i;
for (int i = 0; i < G.vexnum; ++i)//初始化 邻接矩阵,边(路径)的权值,均值为最大值MaxInt
{
for (int j = 0; j < G.vexnum; ++j)
{
if (i == j)
G.arcs[i][j] = 0; //本村庄到本村庄的路径长度为0
else
G.arcs[i][j] = MaxInt; //某村庄到其余各个村庄的路径初始化为MaxInt
}
}
for (int d = 0; d < G.vexnum; d++)