贪心算法 Dijkstra 单源最短路径

http://zhenpengday.blog.163.com/blog/static/1659881432011458242523/

单源最短路径问题定义:

      给定一个图G = (V, E) ,其中每条边的权是一个非负实数。另外给定V 中的一个顶点v ,称为源。求从源v 到所有其它各个顶点的最短路径。

单源最短路径贪心选择策略:
      选择当前从源v出发用最短的路径所到达的顶点,这就是目前的局部最优解。

Dijkstra算法思想:
      首先设置一个集合 S ;用数组 dis[] 来记录 v 到 S 中各点的当前最短路径长度。然后不断地用贪心选择来扩充这个集合,并同时记录或修订数组 dis[] ;直至 S 包含所有 V 中顶点。

具体算法的例子:

Description

用Dijkstra算法实现单源最短路径问题。

Input
第一行:n。代表n个顶点。其中第一个顶点为源点 第二行:c11 c12 c13....c1n (以下n行合起来为n*n的权矩阵,cij代表了i点到j点的边的权值,-1代表无穷大.每行n个数,数与数之间空格隔开) 第三行:c21 c22 c23....c2n ... 第n行:cn1 cn2 cn3....cnn
Output
1-2:最短距离(第i点到1的最短距离,冒号后面无空格,直接是最短距离的值。) 1-3:最短距离 ... 1-n:最短距离
Sample Input
5 0 10 -1 30 100 10 0 50 -1 -1 -1 50 0 20 10 30 -1 20 0 60 100 -1 10 60 0
Sample Output

1-2:10 1-3:50 1-4:30 1-5:60

代码:

#include <stdio.h>

#include <stdlib.h>

int const maxint = 10000000;

void Dijkstra(int n, int v, int * dist, int *prev, int **c)

{

         //建立保存已找到最近的节点

         bool *s;

         s = (bool *) malloc(sizeof(bool) * (n+1));

         //循环初始化原点到各边的距离

         for(int i = 1; i <= n; i++)

         {

                   dist[i] = c[v][i];

                   s[i] = false;

                   if(dist[i] == -1)

                            prev[i] = 0;

                   else

                            prev[i] = v;

         }

         dist[v] = 0;

         s[v] = true;

       for(int o = 1; o <= n; o++)

         {

                   //设置最大值为

                   int temp = maxint;

                   //默认为原点

                   int u = v;

                   //循环,不断从dist中找出距离原点最近的节点,记录到s[]中。

                   for(int j = 1; j <= n; j++)

                   {

                            if(!s[j] && (dist[j] != -1) && (dist[j] < temp))

                            {

                                     u = j;

                                     temp = dist[j];

                            }    

                   }

                   //将其加入已找到的最短距离的数组中

                   s[u] = true;

                  

                   //修改dist[]里面的值,根据贪心性质,记录到余下节点的最短的值

                   for(int k = 1; k <= n; k++)

                   {

                            if(!s[k] && (c[u][k] != -1))

                            {

                                     int newdist = dist[u] + c[u][k];

                                     //修改原点到个边的距离

                                     if( (newdist < dist[k]) || dist[k] == -1 )

                                     {

                                               dist[k] = newdist;

                                               prev[k] = u;

                                     }

                            }

                   }

         }

}

int main(void)

{

         //顶点的个数

         int n;

         scanf("%d", &n);

         //分配数组空间

         int ** c;

         c = (int **)malloc(sizeof(int) * (n+1));

         //分配记录最短距离数组

         int * dist;

         dist = (int *) malloc(sizeof(int) * (n+1));

         dist[0] = -1;

         //分配记录前驱数组

         int * prev;

         prev = (int *) malloc(sizeof(int) * (n+1));

         prev[0] = -1;

         //矩阵,从下标1开始

         for(int i = 1; i <= n; i++)

         {

                   c[i] = (int *)malloc(sizeof(int) * (n+1));

                   c[i][0] = -1;

         }

         //读取矩阵数据

         for(int j = 1; j <= n; j++)

         {

                   for(int k = 1; k <= n; k++)

                   {

                            scanf("%d", &c[j][k]);

                   }

         }

         //执行Dijkstra算法

         Dijkstra(n, 1, dist, prev, c);

         //回归输出结果

         for(int k = 2; k <= n; k++)

         {

                   printf("1-%d:%d\n", k, dist[k]);

         }

         return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值