一、简介
根据传入的景点之间的路费邻接矩阵,找到两点之间费用最少的路径
二、代码
#include <stdio.h>
#define INFINITE 1000 // 定义无穷大为1000,根据实际需求可以定义的更大
#define LEN 10 // 城市的个数
// 邻接矩阵存储的图
// 因为每个景点之间都有路(全连通图),所以路线是无向图,所以没有无穷大
int TOLL[LEN][LEN] = {
0, 8, 31, 4, 15, 77, 88, 11, 12, 13,
8, 0, 24, 5, 6, 23, 33, 11, 12, 13,
31, 24, 0, 6, 7, 2, 12, 11, 12, 13,
4, 5, 6, 0, 18, 8, 36, 11, 12, 13,
15, 6, 7, 18, 0, 66, 77, 11, 12, 13,
77, 23, 2, 8, 66, 0, 4, 11, 12, 13,
88, 33, 12, 36, 77, 4, 0, 11, 12, 13,
11, 11, 11, 11, 11, 11, 11, 0, 14, 14,
12, 12, 12, 12, 12, 12, 12, 14, 0, 15,
13, 13, 13, 13, 13, 13, 13, 14, 15, 0
};
// 标记各顶点是否已经找到最短路径,1表示找到了,0表示没找到
// 经过Init后的值为 1 0 0 0 0 0 0 0 0 0
// 一开始,A已经找到了最短路径,因为A->A的最短路径是0,所以是1,表示找到了,其余没找到的都是0
int final[LEN];
// 最短路径长度(最少花费)
// 经过Init后的值为 0 8 31 4 15 77 88 11 12 13
// 因为是全连通图,所以A可以到B-J中的任意一个地方
int dist[LEN];
// 路径上的前驱
// 用于记录,想到达某一点的最短路径,必须要经过的路线,到达这点的前驱点
// 经过Init后的值为 -1 0 0 0 0 0 0 0 0 0
// 因为A能到达所有的点,所以所有的点前驱点一开始都是0(0代表A)
int path[LEN];
// 用于初始化 dist path final 三个数组
void Init(int x)
{
for (int i = 0; i < LEN; i++) {
final[i] = 0;
}
final[0] = 1;
for (int i = 0; i < LEN; i++) {
dist[i] = TOLL[x][i];
}
for (int i = 0; i < LEN; i++) {
path[i] = x;
}
path[x] = -1;
}
// 算法函数
void Dijkstra(int x)
{
int min; // 用于记录,每次循环没有被访问的城市中,能花最少的钱到的景点
int min_pos; // 用于记录,上述的城市在 dist path final 三个数组中的位置
// 循环查找 LEN -1 次(9次),每次找到通往某一个景点的路径,这个路径是其他通往这个景点的路径中花费的钱最少的
// 通过9次循环就能找到A通往所有城市花费最少钱的路径
for (int j = 0; j < LEN; j++) {
if (j == x) {
continue;
}
min = INFINITE;
// 循环遍历,找到还没确定最短路径,且dist(花费)最小的顶点(景点)
for (int i = 0; i < LEN; i++) {
if (final[i] == 0) {
if (dist[i] < min) {
min_pos = i;
min = dist[min_pos];
}
}
}
final[min_pos] = 1; // 把这个景点设置为已经找到最短路径的状态
// 更新没有找到最短路径的景点dist(花费)和 path(前驱)
for (int i = 0; i < LEN; i++) {
if (final[i] == 0) { // 遍历所有没有找到最短路径的城市dist(花费)
if (TOLL[min_pos][i] + dist[min_pos] < dist[i]) {
// 如果经过景点 min_pos 能够花费更少的钱到达其他的景点,则更新dist为最新的花费的钱的数目
dist[i] = TOLL[min_pos][i] + dist[min_pos];
path[i] = min_pos;
}
}
}
}
}
void printMatrix()
{
printf("\t");
for (int x = 0; x < LEN; x++) {
if (x == 0) {
char A = 'A';
printf("%c\t", A);
}
else if (x == 1) {
char B = 'B';
printf("%c\t", B);
}
else if (x == 2) {
char C = 'C';
printf("%c\t", C);
}
else if (x == 3) {
char D = 'D';
printf("%c\t", D);
}
else if (x == 4) {
char E = 'E';
printf("%c\t", E);
}
else if (x == 5) {
char F = 'F';
printf("%c\t", F);
}
else if (x == 6) {
char G = 'G';
printf("%c\t", G);
}
else if (x == 7) {
char H = 'H';
printf("%c\t", H);
}
else if (x == 8) {
char I = 'I';
printf("%c\t", I);
}
else if (x == 9) {
char J = 'J';
printf("%c\t", J);
}
else {
char N = '?';
printf("%c\t", N);
}
for (int j = 0; j < LEN; j++) {
}
}
printf("\n");
for (int x = 0; x < LEN; x++) {
if (x == 0) {
char A = 'A';
printf("%c\t", A);
}
else if (x == 1) {
char B = 'B';
printf("%c\t", B);
}
else if (x == 2) {
char C = 'C';
printf("%c\t", C);
}
else if (x == 3) {
char D = 'D';
printf("%c\t", D);
}
else if (x == 4) {
char E = 'E';
printf("%c\t", E);
}
else if (x == 5) {
char F = 'F';
printf("%c\t", F);
}
else if (x == 6) {
char G = 'G';
printf("%c\t", G);
}
else if (x == 7) {
char H = 'H';
printf("%c\t", H);
}
else if (x == 8) {
char I = 'I';
printf("%c\t", I);
}
else if (x == 9) {
char J = 'J';
printf("%c\t", J);
}
else {
char N = '?';
printf("%c\t", N);
}
for (int j = 0; j < LEN; j++) {
printf("%d\t", TOLL[x][j]);
}
printf("\n");
}
printf("\n");
}
// 通过给出的要到达的景点,递归的调用他的前驱景点,以此来完成先打印他的前驱景点的任务
void printRoute(int x)
{
if (path[x] != -1) {
printRoute(path[x]);
}
if (x == 0) {
char A = 'A';
printf(" %c", A);
}
else if (x == 1) {
char B = 'B';
printf(" %c", B);
}
else if (x == 2) {
char C = 'C';
printf(" %c", C);
}
else if (x == 3) {
char D = 'D';
printf(" %c", D);
}
else if (x == 4) {
char E = 'E';
printf(" %c", E);
}
else if (x == 5) {
char F = 'F';
printf(" %c", F);
}
else if (x == 6) {
char G = 'G';
printf(" %c", G);
}
else if (x == 7) {
char H = 'H';
printf(" %c", H);
}
else if (x == 8) {
char I = 'I';
printf(" %c", I);
}
else if (x == 9) {
char J = 'J';
printf(" %c", J);
}
else {
char N = '?';
printf(" %c", N);
}
}
void Client() {
int loop = 0;
int x = -1; // 入点
int y = -1; // 出点
while (loop != 1) {
printf("\t\t最少路费路径选择系统\n");
printf("(1)退出当前客户端\t\t(2)查看景点之间路费的邻接矩阵\n");
printf("(3)设置景点出发点和目的地\t(4)输出出发点到目的地之间最短路径\n");
printf("(5)输出出发点到所有景点的最短路径\n");
printf("请输入要执行的命令:");
scanf_s("%d", &loop);
if (loop == 2) {
printMatrix();
}
if (loop == 3) {
printf("用0-9代替A-J输入出发点:");
scanf_s("%d", &x);
printf("用0-9代替A-J输入目的地:");
scanf_s("%d", &y);
printf("\n");
}
if (loop == 4) {
if (x != -1 || y != -1) {
Init(x);
Dijkstra(x);
printf("%c->%c的最少花费为%d,路径为", x + 65, y + 65, dist[y]);
printRoute(y);
printf("\n\n");
}
else
{
printf("未初始化地址\n\n");
}
}
if (loop == 5) {
if (x != -1 || y != -1) {
for (int i = 0; i < LEN; i++) {
Init(x);
Dijkstra(x);
printf("%c->%c的最少花费为%d,路径为", x + 65, i + 65, dist[i]); // 采用ASCII让int转字符
printRoute(i);
printf("\n");
}
}
else
{
printf("未初始化地址\n\n");
}
}
printf("-----------------------------------------------------------------------\n\n");
}
}
int main(void)
{
Client();
return 0;
}