Dijistra(C#)

支持有向与无向图

DijistraSeach.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dijistra
{
    public static class DijistraSeach
    {
        public class SearchResult
        {
            public int Distance { get; private set; }
            public int[] Route { get; set; }
            public SearchResult(int distance, int[] route)
            {
                Distance = distance;
                Route = route;
            }
        }

        /// <summary>
        /// 获取正确的顺序<para/>
        /// 比如footPrint为<para/>
        /// [0] = 0<para/>
        /// [1] = 0<para/>
        /// [2] = 3<para/>
        /// [3] = 0<para/>
        /// [4] = 2<para/>
        /// 从最后一行开始,[4] = 2,意味着[4]的前一个节点为[2],然后看[2] = 3这一行,2的前节点为3,如此循环直到起点。
        /// </summary>
        /// <param name="footPrint">value -> index</param>
        /// <param name="startPoint"></param>
        /// <returns></returns>
        private static int[] findRoute(int[] footPrint, int startPoint = 0)
        {
            var mapSize = footPrint.Length;
            // 反向路径
            var reversedRoute = new int[mapSize];
            // 反向路径中的当前操作序号
            int routeIndex = 0;

            // 添加终点
            reversedRoute[routeIndex] = mapSize - 1;

            routeIndex++;

            // 找到最末节点的前节点
            int previousIndex = footPrint[mapSize - 1];

            // 如果不是起点的话
            while (previousIndex != startPoint)
            {
                // 路径不存在
                if (previousIndex == -1)
                    return null;

                // 记录此节点并继续查找前节点
                reversedRoute[routeIndex] = previousIndex;
                routeIndex++;
                previousIndex = footPrint[previousIndex];
            }

            // 添加起点
            reversedRoute[routeIndex] = startPoint;

            // 将反向路径反向
            var route = new List<int>(mapSize);
            for (int i = routeIndex; i >= 0; i--)
            {
                route.Add(reversedRoute[i]);
            }
            return route.ToArray();
        }

        /// <summary>
        /// search for the shortest route.
        /// </summary>
        /// <param name="routes">an array which contains {pointA, pointB, distance}
        /// <para/>e.g.
        /// <para/>var map = new[] {
        /// <para/>    new []{0,1,10},
        /// <para/>    new []{0,3,30},
        /// <para/>    new []{0,4,100},
        /// <para/>    new []{1,2,50},
        /// <para/>    new []{2,4,10},
        /// <para/>    new []{3,2,20},
        /// <para/>    new []{3,4,60},
        /// <para/>};
        /// </param>
        /// <param name="mapSize">size</param>
        /// <param name="startPoint"></param>
        /// <param name="directional"></param>
        /// <returns></returns>
        public static SearchResult Search(int[][] routes, int mapSize, int startPoint , bool directional)
        {
            // record all minIndex found during the searching progress.
            var footPrint = new int[mapSize];
            // to avoid dead searching loop.
            var visted = new bool[mapSize];
            // accumulated distance from startPoint to each index.
            var milestones = new int[mapSize];

            // initialize map.
            var map = new int[mapSize, mapSize];
            for (int i = 0; i < mapSize; i++)
            {
                for (int j = 0; j < mapSize; j++)
                {
                    map[i, j] = i == j? 0 : int.MaxValue;
                }
            }

            // build map.
            foreach (var route in routes)
            {
                map[route[0], route[1]] = route[2];

                if (!directional)
                {
                    // make the map non-directional.
                    map[route[1], route[0]] = route[2];
                }
            }

            // initialize milestones by distance between each node and startPoint.
            for (int i = 0; i < mapSize; i++)
            {
                milestones[i] = map[startPoint, i];
                // wether i is connected to startPoint or not;
                if (milestones[i] != int.MaxValue)
                {
                    footPrint[i] = startPoint;
                }
                else
                {
                    footPrint[i] = -1;
                }
            }

            // start searching.
            for (int j = 0; j < mapSize; j++)
            {
                // find the nearest from this index.
                // milestones has already been updated to fit the minIndex.
                int localMin = int.MaxValue, minIndex = startPoint;
                for (int i = 0; i < mapSize; i++)
                {
                    if (!visted[i] && milestones[i] < localMin)
                    {
                        minIndex = i;
                        localMin = milestones[i];
                    }
                }

                visted[minIndex] = true;

                // update milestones.
                for (int i = 0; i < mapSize; i++)
                {
                    // index not connected to minIndex is not connected to
                    if (map[minIndex, i] == int.MaxValue) continue;
                    if (visted[i]) continue;

                    // accumulate distance from startPoint to minIndex;
                    var newDis = milestones[minIndex] + map[minIndex, i];
                    if ((newDis < milestones[i]))
                    {
                        milestones[i] = newDis;
                        footPrint[i] = minIndex;
                    }
                }
            }

            // the end is beyond reach.
            if (milestones[mapSize - 1] == int.MaxValue)
                return null;

            var resultRoute = findRoute(footPrint, startPoint);
            var result = new SearchResult(milestones[mapSize - 1], resultRoute);
            return result;
        }
    }
}

Main.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dijistra
{
    class Program
    {
        static void Main(string[] args)
        {
            // 无向图
            // 使用此外图时,需将DijistraSeach.Search的directional参数设为false,mapSize=5
            var nonDirectionalMap = new[] {
                new []{0,1,10},
                new []{0,3,30},
                new []{0,4,100},
                new []{1,2,50},
                new []{2,4,10},
                new []{3,2,20},
                new []{3,4,60},
            };

            // 有向图
            // 使用此外图时,需将DijistraSeach.Search的directional参数设为true,mapSize=2
            var directionalMap = new[]{
                new []{1, 0, 10},
                new []{0, 1, 11},
            };

            var result = DijistraSeach.Search(
                routes: nonDirectionalMap,
                mapSize: 5,
                startPoint: 0,
                directional: false
                );

            if (result == null)
            {
                Console.WriteLine("Can‘t find the route.");
            }
            else
            {
                Console.WriteLine(
                "Shortest distance is {0}\nroute : {1}\n",
                result.Distance,
                String.Join("->", result.Route)
                );
            }

        }
    }
}

Dijistra(C#)

时间: 2024-08-27 05:11:54

Dijistra(C#)的相关文章

javascript实现有向无环图中任意两点最短路径的dijistra算法

有向无环图 一个无环的有向图称做有向无环图(directed acycline praph).简称DAG 图.DAG 图是一类较有向树更一般的特殊有向图, dijistra算法 摘自 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijk

dijistra和Folyd模板

dijistra模板 1 void dijistra(int x){ 2 int pos = x; 3 for(int i = 1; i <= n; i ++){ 4 dist[i] = g[i][pos]; 5 } 6 vis[pos] = true; 7 for(int i = 1; i <= n; i ++){ 8 int mins = INF; 9 for(int j = 1; j <= n; j ++){ 10 if(!vis[j] && dist[j] <

A strange lift(Dijistra优化)

A strange lift Problem Description There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the butto

UVA 11374 Airport Express 机场快线 Dijistra+路径

题目链接:UVA 11374 Airport Express Airport Express Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]   [Go Back]   [Status] Description Problem D: Airport Express In a small city called Iokh, a train service, Airport-Expr

51nod-迷宫问题(Dijkstra算法)

Dijkstra算法 你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数.还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间.游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点,在满足首要目标的前提下,使得你的得分总和尽可能大.现在问题来了,给定房间.道路.分数.起点和终点等全部信息,你能计算在尽快离开迷宫的前提下,你的最大得分是多少么? Dijkstra算法是一个经典的算法--他是荷兰计算机科学家D

省选游记

作为一个傻逼的二等奖,我作为非正式选手参加了湖南OI 2017 年的比赛. D1: T1:似乎试题除了问题,我便开始敲平衡树的板子度过时间,结果,试题下来,第一题便是平衡树,这在一定程度上让我很开心,因为splay我算是比较熟悉,所以没有在题目上花费多少时间.然而,在我发现这个splay甚至不要平衡时,我选择了指针写法,这也让我失去了这次比赛最大的得分点,成为了一个最大的遗憾,最后,指针段错误,0分. T2:暴力很好写,但我事实上没有任何数据结构的实战经验,这也是这次考试发现的最大问题,最后,我

Boyer-Moore (C#)

调用ShowExample方法即可查看结果 使用Debug配置编译可以查看详细匹配过程 using System; using System.Collections.Generic; namespace Dijistra { /// <summary> /// An implemention of Boyer-Moore algorithm. /// <para/>author : Ornithopter /// </summary> class BoyerMooreS

HDU 2544(floyd+bellman-ford+floyd+dijkstra队列优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目大意:找点1到点n的最短路(无向图) 练一下最短路... dijkstra+队列优化: 1 #include<iostream> 2 #include<functional> 3 #include<vector> 4 #include<queue> 5 using namespace std; 6 typedef pair<int, int>

索引优先队列的工作原理与简易实现

欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 优先队列与索引优先队列 优先队列的原理大家应该比较熟悉,本质上就是利用完全二叉树的结构实现以log2n的时间复杂度删除队列中的最小对象(这里以小堆顶为例).完全二叉树又可以通过数组下标实现索引,当插入一个对象的时候,利用上浮操作更新最小对象.当删除堆顶最小对象时,将末尾的对象放置到堆顶上,然后执行下沉操作. 优先队列有一个缺点,就是不能直接访问已存在于优先队列中的对象,并更新它们