计算完全最短路径的Floyd算法

(—)问题描述

  • 给定一个加权连通图(有向的或者无向的),完全最短路径问题要求找到从每个顶点到其他顶点之间的距离(最短路径长度)。图的最短路径问题有若干个变化形式,这是其中的一种。最短路径的最新应用是对计算机游戏中的路径规划距离进行预先计算。

(二)解题思路

  • 1.首先定义一个二维数组arr来存放图的权重矩阵。

  • 2.再定义一个二维数组path,用来标记图的最短路径途径的点有哪些。

  • 3.假设图中有n个顶点,则需要对矩阵arr和矩阵path进行N次更新,初始时矩阵
    arr[i] [j]表示为顶点i到顶点j的权值,如果顶点i不能到j则用一个极大值来表示,接下来开始对矩阵进行更新,无外乎为两种情况如果arr[i][j]>arr[i][k]+arr[k][j] (表示为从顶点i到顶点j的话可以途径顶点k来获取一个最短路径,然后再用path[i][j]=k来标记这个最短路径所经过的中间点),反之则是arr[i][j]直接从i到j的距离最短。

  • 重复步骤3更新出所有顶点的路径的中间点,得到最后的path数组。

我们以下图的路径为例:

在这里插入图片描述

  • 对于path数组我们开始没更新的时候可以给它的整体赋值为负一,然后再逐步更新,在求路径时可以通过递归运用path数组来求它的路径。
  • 根据上图我们可以先得出其权重矩阵,然后输入其权重矩阵,再逐步求出最短路径。
代码如下所示:
// 测试用.cpp : 定义控制台应用程序的入口点。
//

	#include "stdafx.h"

	#define MAX 1000
	int arr[MAX][MAX]; //做距离矩阵用
	int path[MAX][MAX];//标记中间点
	int n;//返回矩阵有多少个阶
		
	int Floyd()
	{
		int i, j, k;

		for (int k = 0; k < n; k++)
		{
			for (int i = 0; i < n; i++)
			{
				for (int j = 0; j < n; j++)
				{
					if (arr[i][j]>arr[i][k] + arr[k][j])//如果从i直接到j的距离大于从                     i到k到j的距离
					{	
						arr[i][j] = arr[i][k] + arr[k][j];//设置中间结点k,表示先从i点到k点再到j点
						path[i][j] = k;//标记中间到达的点k

					}
				}
			}
		}
		return 0;
	}

	void showpath(int path[MAX][MAX], int i, int j)
	{
		if(path[i][j] != -1)
		{
			
			int middle = path[i][j];
			showpath(path, i,middle);//运用递归一直返回到最初的标记点,再逐个显示出路径
			printf("%d->", path[i][j]);

		}
		else{
		
			
		
		}
	
	
	}



	int main()
	{
		printf("请输入矩阵的阶数:");
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				path[i][j] = -1;


			}

		}
		printf("请输入图的权重矩阵:(若无法到达则输入-1)");
		printf("\n");
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				scanf("%d", &arr[i][j]);
				if (arr[i][j] == -1)
				{
					arr[i][j] = 1000000;//将无法到达的边赋值为一个极大值

				}


			}

		}
		Floyd();
		printf("图的距离矩阵为:");
		printf("\n");
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				printf("%d\t", arr[i][j]);


			}
			printf("\n");
		}

		printf("由此得出路径矩阵为:");
		printf("\n");
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				printf("%d\t", path[i][j]);

			}
			printf("\n");

		}

		int x, y;
		printf("请输入起点和终点(返回的是最近的路径):");
		scanf("%d%d", &x, &y);
		printf("%d->", x);
		showpath(path, x, y);
		printf("%d", y);

	}

结果如下图所示:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值