Floyd-Warshall算法(求解任意两点间的最短路) 详解 + 变形 之 poj 2253 Frogger

/*
好久没有做有关图论的题了,复习一下。
---------------------------------------------------------

任意两点间的最短路(Floyd-Warshall算法)
动态规划:
dp[k][i][j] := 节点i可以通过编号1,2...k的节点到达j节点的最短路径。

使用1,2...k的节点,可以分为以下两种情况来讨论:
	(1)i到j的最短路正好经过节点k一次
		dp[k-1][i][k] + dp[k-1][k][j]
	(2)i到j的最短路完全不经过节点k
		dp[k-1][i][j]
故:dp[k][i][j] = min(dp[k-1][i][k] + dp[k-1][k][j], dp[k-1][i][j])

空间可优化:dp[i][j] = min(dp[i][k] + dp[k][j], dp[i][j])

初始值:
	dp[0][i][j] = 0 (i == j)
	dp[0][i][j] := 边i->j的权值
	如果i和j之间不存在边,dp[i][j] = INF (0x3f3f3f3f)

时间复杂度:O(|V|^3)
可以处理边是负数的情况,判断图中是否有负圈,只需检查是否存在dp[i][i]是负数的顶点i就可以了。

---------------------------------------------------------------------------------
poj 2253 Frogger
对于此题,求的是:
	To execute a given sequence of jumps, a frog‘s jump range obviously must be at least 
	as long as the longest jump occuring in the sequence.
	The frog distance (humans also call it minimax distance) between two stones therefore is defined as
	the minimum necessary jump range over all possible paths between the two stones. 
	即:一条路径中需要跳跃很多次,但存在一次跳跃在所有跳跃中需要跳的距离最长,这个距离即可称为这条路径中需要跳跃的最长距离,
	    找出A石头到达B石头所有路径的需要跳跃的最长距离,其中最短的最长距离即为答案,即:The frog distance。

Floyd-Warshall算法会遍历到i->j所有的路径,所以我们可以改变dp状态,解决此问题:
	dp[k][i][j] := 节点i可以通过编号1,2...k的节点到达j节点的路径中,需要跳跃的最短的最长距离。
	故:
	dp[k][i][j] = min(dp[k-1][i][j], max(dp[k-1][i][k], dp[k-1][k][j]))

优化一下:
	dp[i][j] := min(dp[i][j], max(dp[i][k], dp[k][j]))

初始值:
	dp[0][i][j] := 从节点i到节点j的距离。
*/
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstddef>
  5 #include <iterator>
  6 #include <algorithm>
  7 #include <string>
  8 #include <locale>
  9 #include <cmath>
 10 #include <vector>
 11 #include <cstring>
 12 #include <map>
 13 #include <utility>
 14 #include <queue>
 15 #include <stack>
 16 #include <set>
 17 using namespace std;
 18 const int INF = 0x3f3f3f3f;
 19 const int MaxN = 205;
 20 const int modPrime = 3046721;
 21
 22 struct Node
 23 {
 24     double x, y;
 25 };
 26
 27 int n;
 28 Node nodeSet[MaxN];
 29 double dp[MaxN][MaxN];
 30 double dis[MaxN][MaxN];
 31
 32 void getDistance()
 33 {
 34     for (int i = 1; i <= n; ++i)
 35     {
 36         for (int j = 1; j <= n; ++j)
 37         {
 38             if (i != j)
 39             {
 40                 dis[i][j] = sqrt((nodeSet[i].x - nodeSet[j].x)*(nodeSet[i].x - nodeSet[j].x) +
 41                                  (nodeSet[i].y - nodeSet[j].y)*(nodeSet[i].y - nodeSet[j].y));
 42                 dis[j][i] = dis[i][j];
 43             }
 44             else
 45             {
 46                 dis[i][j] = 0.0;
 47             }
 48         }
 49     }
 50 }
 51
 52 void Solve()
 53 {
 54     for (int i = 1; i <= n; ++i)
 55     {
 56         for (int j = 1; j <= n; ++j)
 57         {
 58             dp[i][j] = dis[i][j];
 59         }
 60     }
 61     for (int k = 1; k <= n; ++k)
 62     {
 63         for (int i = 1; i <= n; ++i)
 64         {
 65             for (int j = 1; j <= n; ++j)
 66             {
 67                 dp[i][j] = min(dp[i][j], max(dp[i][k], dp[k][j]));
 68             }
 69         }
 70     }
 71     printf("Frog Distance = %.3lf\n\n", dp[1][2]);
 72
 73 }
 74
 75 int main()
 76 {
 77 #ifdef HOME
 78     freopen("in", "r", stdin);
 79     //freopen("out", "w", stdout);
 80 #endif
 81
 82     int num = 1;
 83     while (~scanf("%d", &n) && n)
 84     {
 85         for (int i = 1; i <= n; ++i)
 86         {
 87             scanf("%lf %lf", &nodeSet[i].x, &nodeSet[i].y);
 88         }
 89         getDistance();
 90         printf("Scenario #%d\n", num);
 91         Solve();
 92         ++num;
 93     }
 94
 95
 96 #ifdef HOME
 97     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
 98     _CrtDumpMemoryLeaks();
 99 #endif
100     return 0;
101 }


时间: 2024-12-27 23:32:36

Floyd-Warshall算法(求解任意两点间的最短路) 详解 + 变形 之 poj 2253 Frogger的相关文章

任意两点间的最短路 Floyd及其本质

我们知道在已知起点的情况下,求到其他任何一点的最短路是用dijkstra,那么在一个有向图中,我们想知道任意两点之间的最短路,我们就可以使用floyd,而且这个算法表面看起来非常的简单,就是一个三重循环,如果这个图有N个点,那么复杂度为O(|N|3),代码如下. 1 for(int k=0;k<n;k++) 2 for(int i=0;i<n;i++) 3 for(int j=0;j<n;j++) 4 d[i][j]=min(d[i][j],d[i][k]+d[k][j]); 在复杂度这

AOJ -0189 Convenient Location (任意两点间的最短路)

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=78207 看懂题就好. 求某一办公室到其他办公室的最短距离. 多组输入,n表示n条关系,下面n次每次输入 x y d表示x到y的距离是d. 输出办公室的编号和距离. 因为 顶点数小于10,直接floyed求出所有距离之后,枚举出最短距离即可. 1 /* *********************************************** 2 Author : zch

Dijkstra算法(求解单源最短路)详解 + 变形 之 poj 1860 Currency Exchange

/* 求解单源最短路问题:Dijkstra算法(该图所有边的权值非负) 关键(贪心): (1)找到最短距离已经确定的节点,从它出发更新与其相邻节点的最短距离: (2)此后不再关心(1)中“最短距离已经确定的节点”. 时间复杂度(大概的分析,不准确): “找到最短距离已经确定的节点” => O(|V|) "从它出发更新与其相邻节点的最短距离" => 邻接矩阵:O(|V|),邻接表:O(|E|) 需要循环以上两个步骤V次,所以时间复杂度:O(V^2) 即:在|E|较小的情况下,

任意两点间的最短路问题 Floyd-Warshall算法

这一算法与之前的Bellman-F=Ford算法一样,都可以判断负环 只需要检查dp [i] [j] 是负数的顶点i即可 1 // 求解任意两点间的最短路径问题 2 // Floyed-Warshall算法 3 // 复杂度O(N^3),N为顶点数 4 5 #include <cstdio> 6 #include <iostream> 7 8 using namespace std; 9 // 用dp的思路来求解 10 // dp[k][i][j]:从i到j,只利用前K个节点的最短

基于pgrouting的任意两点间的最短路径查询函数二

在前面的博文中写过一篇查询任意两点间最短路径的函数,当时对pgrouting不熟悉,功能很low.现在对该函数进行扩展,支持用户自己输入查询的数据库表,这一点看似简单,其实意义很大,在做室内导航的时候当用户所在的楼层变化的时候最短路径函数查询的数据表名称也会发生变化,不可能一栋大楼里的道路都是一样的吧,另外进行跨楼层的最短路径规划时,需要查询从A到楼梯口的最短路径和楼梯口到B的最短路径,这些都需要进行最短路径规划的时候能够自己选择数据表. DROP FUNCTION pgr_fromAtoB(t

基于pgrouting的任意两点间的最短路径查询函数

前面文章介绍了如何利用postgresql创建空间数据库,建立空间索引和进行路径规划.但是在真实的场景中用户进行路径规划的时候都是基于经纬度数据进行路径规划的,因为用户根本不会知道道路上节点的ID.因此文本讲述如何查询任意两点间的最短路径. 一.定义函数名及函数参数 函数名定义为: pgr_fromAtoB 参数设置分别为: 输入为数据库表名,起点和终点的经纬度坐标 输出为:路段序号,gid号,道路名,消耗及道路集合体. IN tbl varchar, --数据库表名 IN x1 double

图论之最短路02-1——任意两点间最短距离及路径

======================================================== 求任意两点间最短距离及其路径.(万能最短路) 输入:权值矩阵,起点,终点 输出:最短距离矩阵,指定起讫点路径(经过的顶点编号) 为任意一点到其他点最短路奠定基础 ======================================================== function [P d]=liangdianzuiduanlu(W,qidian,zhongdian) W

图论之最短路02-2——改进的任意两点间最短距离及路径

======================================================== 重要程度 ***** 求任意两点间最短距离及其路径.(万能最短路) 输入:权值矩阵,起点,终点 输出:最短距离矩阵,指定起讫点路径(经过的顶点编号) ======================================================== function renyizuiduanlu(W) clc disp('                        

任意两点间最短距离floyd-warshall ---- POJ 2139 Six Degrees of Cowvin Bacon

floyd-warshall算法 通过dp思想 求任意两点之间最短距离 重复利用数组实现方式dist[i][j] i - j的最短距离 for(int k = 1; k <= N; k++) for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]); 非常好实现 O(V^3) 这里贴一道刚好用到的题 http://poj.org