今天看了一下午的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;
}