Djikstra理解1

5 篇文章 0 订阅

今天看了一下午的djikstra,到了晚上才理解了一点,做下记录吧。。。。。

这个算法我感觉很low,我觉得像暴力破解一样,很像动态规划,就是每一部都是最优解(局部最优解),到最后就形成了(整体的最优解)。

就如下方的例题,在求图中(这里的图可以是有向图和无向图)一点到另一点的最近距离时,先求出距离起始点最近的点然后,

分别求出其他的点到终点的距离,这里要注意,因为图并不是每个都是相连的

如图:

 

 

 

 

比如让求a点到d点的最优路径,djikstra的做法如下,

基本思想:选取a点,然后遍历a点周围的点,这里要注意图中与a相连的点之间的距离为横线上的数字,但不和a点相连的,e,d,c他们与a的距离就为无穷大,反正是比a点到f,或g,或b的距离大,然后选择距离a最近的点b,然后更新a点到各点的距离,原来a点与c点之间是无穷的,现在经过b,可以将其变成2+6=8这里的8当然小于原来的无穷的,所以用8替换无穷大,这里可以把b看出一个介质,经过b使得a与c相连,然后将b标记,标记表示已经走过了,然后接着遍历距离a最近的点,注意b点已经被排除了,接着是f点,f点又可以连接e和g点,这样就可以用4+3=7更新a点到e点的原来无穷大的的距离,但a->f->g的距离大于a->g的距离,所以不替换,这样就可以同过局部的最优解一步一步的逼近整体的最优解。

下面上例题:

 

某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。 

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

Input

本题目包含多组数据,请处理到文件结束。 
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。 
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。 
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。

Output

对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1. 

Sample Input

3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2

Sample Output

2
-1

下面给出ac的代码:

#include <iostream>
#include <cstring>
#define inf 0x3f3f3f
int maps[205][205];
int vis[205],m,n;
using namespace std;
void djikstra(int s)
{
    int k=-1,tem;
    memset(vis,0,sizeof vis);///初始化标记数组
    vis[s]=1;///将起始点标记
    for(int i=0; i<n; i++)
    {
        tem=inf;
        ///找出除标记的距离源点最近的点
        for(int j=0; j<n; j++)
        {
            if(!vis[j]&&maps[s][j]<tem)
            {
                k=j;
                tem=maps[s][j];
            }
        }
        ///若距离源点最近的为inf那么肯定不能到达终点
        if(tem==inf)break;
        vis[k]=1;///将找出的点标记
        for(int j=0; j<n; j++)
        {
            ///取出路径最近的赋给
            if(!vis[j]&&(maps[s][j]>(maps[s][k]+maps[k][j])))
                maps[s][j]=maps[s][k]+maps[k][j];
        }

    }
}
int main()
{
    int a,b,x,s,t,i,j,N;
    while(cin>>n>>m)
    {
        ///初始化
        for(i=0; i<n; i++)
        {
            for(j=0; j<n; j++)
                maps[i][j]=inf;
            maps[i][i]=0;
        }
        for(i=0; i<m; i++)
        {
            cin>>a>>b>>N;
            if(N>maps[a][b]){}
            else maps[b][a]=maps[a][b]=N;//这里巨坑注意注意!!!!!!!!!!!!

        }
        cin>>s>>t;
        djikstra(s);
        if(maps[s][t]==inf)cout<<"-1\n";
        else cout<<maps[s][t]<<"\n";
    }
    return 0;
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值