关于Dijkstra算法的博文

http://www.cnblogs.com/skywang12345/p/3711512.html#anchor2


Dijkstra算法是一个经典的算法——他是荷兰计算机科学家Dijkstra于1959年提出的单源图最短路径算法,也是一个经典的贪心算法。所谓单源图 是规定一个起点的图,我们的最短路径都是从这个起点出发计算的。算法的适用范围是一个无向(或者有向图),所有边权都是非负数。

 
算法描述:

节点集合V = {}空集合,距离初始化。
节点编号0..n – 1, 起点编号0≤ s < n。

距离数组
起点 d[s] = 0
其他 d[i] = ∞, 0 ≤ i < n,  i ≠ s。
 
循环n次

找到节点i 不属于 V,且d[i]值最小的节点i。

V = V + i

对所有满足j  V的边(i, j) 更新d[j] = min(d[j] , d[i] + w(i,  j))。

以下图为例,描述Dijkstra算法的运行过程:
 
初始,求A点到其他点的最短路径(也称单源最短路径)。
初始化A点
A点有3条边,AB(17),AE(16),AF(1)。
将3条边加入优先队列,此时队列中的元素为(只记录目标点):

{1 F} | {16 E} | {17 B}

 
取出队列中最小的元素,{1 F},F点是一个未处理过的点,因此得到了A点到F点的最短距离。更新距离,变为:
处理F点,F点有4条边。FA(1),FB(11),FD(14),FE(33)。其中FA已经处理过,所以忽略掉。

将3条边加入优先队列,注意,此时加入队列时,所有边的权值需要加上F点到A点的最短距离1。此时队列中的元素为:

{12 B} | {15 D}  | {16 E} | {17 B} | {34 E}

 
取出队列中最小的元素,{12 B},B点是一个未处理过的点,因此得到了A点到B点的最短距离。更新距离,变为:
 
处理B点,B点有4条边。AB(17),BF(11),BC(6),BD(5)。其中AB,BF已经处理过,所以忽略掉。

将2条的权值加上A到B的最短路径12,加入优先队列。此时队列中的元素为:

{15 D}  | {16 E} | {17 B} | {17 D} | {18 C} | {34 E}

取出队列中最小的元素,{15 D},D点是一个未处理过的点,因此得到了A点到D点的最短距离。更新距离,变为:

处理D点,D点有4条边。其中DC(10),DE(4)没有处理过。

将2条的权值加上A到D的最短路径15,加入优先队列。此时队列中的元素为:

{16 E} | {17 B} | {17 D} | {18 C} | {19 E} | {25 C} | {34 E}

取出队列中最小的元素,{16 E},E点是一个未处理过的点,因此得到了A点到E点的最短距离。更新距离,变为:

处理E点,E点所连接的边都已经被处理过了。

此时优先队列中的元素为:
{17 B} | {17 D} | {18 C} | {19 E} | {25 C} | {34 E}

取出队列中最小的元素,{17 B},B点是一个已经处理过的点,因此继续后面的处理。

 
 {17 D} | {18 C} | {19 E} | {25 C} | {34 E}
 
取出队列中最小的元素,{17 D},D点是一个已经处理过的点,因此继续后面的处理。
 
 {18 C} | {19 E} | {25 C} | {34 E}

取出队列中最小的元素,{18 C},C点是一个未处理过的点,因此得到了A点到C点的最短距离。更新距离,变为:

Dijkstra算法的证明:

i  V,  d[i] = min{d[x] + w(x, i), x  V}

我们证明节点i要进入集合V时,d[i]确实是s到i的最短路长度 。
归纳证明: 起初 d[s] = 0满足条件。

假设之前集合V中的点全部满足假设,现在要加入节点i   V,假设任意从s到i的路径P= s…x y…i。
其中s..x全部在V中, y  V。根据归纳假设d[x]是s到x的最短路长度。
根据d的定义,我们有d[x] + w(x,y) ≥ d[y]。
而且因为dijkstra选择最小的d加入,所以有d[y] ≥ d[i] 。
于是有路径P的长度, length(P) ≥  d[x] + w(x, y) + length(y..i) ≥ d[y] + length(y..i)  ≥  d[y] ≥ d[i]。
从而d[i]也是最短路的长度。得证。
最后,我们来提供输入输出数据,由你来写一段程序,实现这个算法,只有写出了正确的程序,才能继续后面的课程。


 

Dijkstra算法

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

 
输入

第一行4个整数n (<=500), m, start, end。n表示房间的个数,房间编号从0到(n - 1),m表示道路数,任意两个房间之间最多只有一条道路,start和end表示起点和终点房间的编号。
第二行包含n个空格分隔的正整数(不超过600),表示进入每个房间你的得分。
再接下来m行,每行3个空格分隔的整数x, y, z (0<z<=200)表示道路,表示从房间x到房间y(双向)的道路,注意,最多只有一条道路连结两个房间, 你需要的时间为z。
输入保证从start到end至少有一条路径。
输出
 
一行,两个空格分隔的整数,第一个表示你最少需要的时间,第二个表示你在最少时间前提下可以获得的最大得分。
 
输入示例

3 2 0 2
1 2 3
0 1 10
1 2 11
输出示例

21 6

大佬的代码

#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>
#define INF 0x3f3f3f3f
using namespace std;
const int MAX = 550;
int co[MAX], dist[MAX], g[MAX][MAX],low[MAX];
int n, m, s, e;
bool vis[MAX];
void dijistra(){
for(int i = 0; i < n; i ++){
dist[i] = INF;
}
memset(vis,0,sizeof(vis));
memset(low,0,sizeof(vis));
dist[s] = 0;
low[s] = co[s];
for(int i = 1; i <= n; i ++){
int mins = INF, MAx = 0, pos;
for(int j = 0; j < n; j ++){
if(!vis[j] && dist[j] < mins){
pos = j;
mins = dist[j];
MAx = co[j];
}
if(!vis[j] && dist[j] == mins && MAx < low[j]){
pos = j;
MAx = low[j];
}
}
if(mins == INF)break;
vis[pos] = true;
for(int j = 1; j <= n; j ++){
if(!vis[j] && dist[j] > dist[pos] + g[pos][j]){
dist[j] = dist[pos] + g[pos][j];
low[j] = low[pos] + co[j];
}
if(!vis[j] && low[j] < low[pos] + co[j] && dist[j] == dist[pos]+g[pos][j]){
low[j] = low[pos] + co[j];
}
}
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&e);
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++)
g[i][j] = (i==j)?0:INF;
}
for(int i = 0; i < n; i ++) scanf("%d",&co[i]);
for(int i = 0; i < m; i ++) {
int u, v, w;
scanf("%d%d%d",&u,&v,&w);
if(g[u][v] > w) {
g[u][v] = g[v][u] = w;
}
}
dijistra();
printf("%d %d\n",dist[e],low[e]);
return 0;
}

  

 

51nod-迷宫问题(Dijkstra算法)的更多相关文章

  1. Dijkstra算法详细(单源最短路径算法)

    介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或 ...

  2. 图论篇3——最短路径 Dijkstra算法、Floyd算法

    最短路径 问题背景:地图上有很多个城市,已知各城市之间距离(或者是所需时间,后面都用距离了),一般问题无外乎就是以下几个: 从某城市到其余所有城市的最短距离[单源最短路径] 所有城市之间相互的最短距离 ...

  3. 求两点之间最短路径-Dijkstra算法

     Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.D ...

  4. Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解

    /* Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次. 要知道,我们从队列头部找到的都是到 已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其 ...

  5. 关于dijkstra算法的一点理解

    最近在准备ccf,各种补算法,图的算法基本差不多看了一遍.今天看的是Dijkstra算法,这个算法有点难理解,如果不深入想的话想要搞明白还是不容易的.弄了一个晚自习,先看书大致明白了原理,就根据书上的 ...

  6. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

  7. Dijkstra算法(二)之 C++详解

    本章是迪杰斯特拉算法的C++实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法图解 3. 迪杰斯特拉算法的代码说明 4. 迪杰斯特拉算法的源码 转载请注明出处:http://www.cnbl ...

  8. Dijkstra算法(一)之 C语言详解

    本章介绍迪杰斯特拉算法.和以往一样,本文会先对迪杰斯特拉算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法 ...

  9. 最短路问题Dijkstra算法

    Dijkstra算法可以解决源点到任意点的最短距离并输出最短路径 准备: 建立一个距离数组d[ n ],记录每个点到源点的距离是多少 建立一个访问数组v[ n ],记录每个点是否被访问到 建立一个祖先 ...

随机推荐

  1. iOS学习之第二个View使用UITabBarViewController

    前面有一篇博文iOS学习之Tab Bar的使用和视图切换 这是在AppDelegate里使用Tabbar,这样的程序打开就是TabbarView了,有时候我们需要给程序做一些帮助页面,或者登录页面,之 ...

  2. 使用net.sf.fjep.fatjar插件将第三方JAR包打包进自已的JAR包中

    一般单个工程,在没有应用别人的jar包时导出为jar很简单,只要设置一个Main-Class就行了,也就是选择程序入口(main所在类).但是涉及到了数据库或需要用到第三方的JAR,就需要用到相应的数 ...

  3. 使用RampTexture来控制diffuse shading

    [RampTexture] RampTexture(渐变纹理),可以是1D/2D纹理. This allows you to accentuate the surface's colors to fa ...

  4. 128. Longest Consecutive Sequence (HashTable)

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  5. Hibernate多对多操作

    ---------------------siwuxie095 Hibernate 多对多操作 以用户和角色为例 (一)多对多映射配置 第一步:创建两个实体类,用户和角色 第二步:让两个实体类之间互相 ...

  6. 【原】Mac下统计任意文件夹中代码行数的工

    [链接][原]Mac下统计任意文件夹中代码行数的工http://www.cnblogs.com/wengzilin/p/4580646.html

  7. Cloudstack4.2之改变数据卷容量的大小(Resize Data Volumes)

    下图标注了这个功能在cloudstack4.2 UI中的位置 在cloudstack中是通过磁盘服务来设定卷的大小的.管理员可以设置相应的磁盘服务以供用户来使用.为了增强系统的灵活性,方便最终用户的使 ...

  8. 怎样在本地电脑上连接另外一台电脑上的mysql数据?(代码示例)

    基本上有两种方式: 1,使用MYSQL的管理工具,可以远程连接,比如用导航猫系列的,只要知道对方IP,然后就可以自己输入账号密码连接了. 2,使用代码连接. Java代码示例: package com ...

  9. 修改字段类型modify

    alter table 表名 modify column 字段名 类型;

  10. LWIP协议栈1

    STM32F4自带的MAC,而没有PHY纯模拟电路部分,没有把PHY做进STM32F4是因为会对芯片的功耗有影响,同时芯片的体积会增大等原因. MAC与PHY的通信接口是MII以及RMII方式. MD ...