• 学习"图"(最短路径)算法


    1、首先上图哈:图的邻接矩阵表示。


    邻接矩阵

    2、图的最短路径

    最短路径

    #include<stdio.h>
    
    #define MAX 10000
    #define N 6
    
    //每个定点到其它顶点的直线距离
    int G[N][N]=
    {
    	{MAX,MAX,10,MAX,30,100},
    	{MAX,MAX,5,MAX,MAX,MAX},
    	{MAX,MAX,MAX,50,MAX,MAX},
    	{MAX,MAX,MAX,MAX,MAX,10},
    	{MAX,MAX,MAX,20,MAX,60},
    	{MAX,MAX,MAX,MAX,MAX,MAX}
    };
    //p表示到达这个点的最短距离路径上的节点
    int p[N][N] =
    {
    	//先给他们初始状态
    	//v0到v可通的就将其下标存起来
    	//v0->v0没意义
    	{0,0,0,0,0,0},
    	//v0->v1不可通
    	{0,0,0,0,0,0},
    	//v0->v2可通,
    	{0,2,0,0,0,0},
    	{0,0,0,0,0,0},
    	{0,4,0,0,0,0},
    	{0,5,0,0,0,0}
    };
    
    void main(){
    	//定义距离数组,把求出来的
    	//v0到其它点的最短距离都存放在这里。
    	int d[N] = {MAX,MAX,10,MAX,30,100};
    	//要计算v0到每个点的最短距离
    	//方法:遍历除v0之外的所有顶点N遍(最外层i循环),
    	//每一遍都找出一个最短距离和经过这个顶点的间接最短距离
    
    	//并且赋值到相应的距离里去。
    	//如果能取出比他更短的,否则就以其原来作为最短距离
    	int flag[N] = {0};
    	int i,v,min,k,j;
    	//一共循环N次
    	for(i=0;i<N;i++){
    		//首先找出v0出发直线距离最短的
    		//min存储了v0到其它点的最短距离
    		//v存储了最短距离对应的顶点。
    		for(k=0,min = MAX,v = 0;k<N;k++){
    			if(flag[k] != 1 && d[k]<min){
    				min = d[k];
    				v = k;
    			}
    		}
    		//将这个最短距离存到v对应的节点里去
    		d[v] = min;
    		//已经算出最短距离的标志为1
    		//在其它循环当中进行排除。
    		flag[v] = 1;
    
    		//开始求间接距离最短
    		for(k=0;k<N;k++){
    			//还没有求出最短距离,
    			//且原来最小的v0到v的直线距离
    			//值加上v到k的距离要比直线距离来的小
    			//说明d[k] 有更小的了。
    			if(flag[k] != 1 && min + G[v][k]<d[k]){
    				d[k] = min + G[v][k];
    				//有些顶点是经过了两个或多个中间节点的
    				//所以要把p[k][0]作为标志
    				if(p[k][0] == 0){//如果没设置过
    					p[k][0] = 1;
    					//是经过v到达k的,所以:
    					p[k][1] = v;
    					p[k][2] = k;
    				}else{//如果设置过了
    					for(j=1;p[v][j];j++)
    						p[k][j] = p[v][j];
    					p[k][j] = k;
    				}
    			}
    		}
    
    	}
    	//打印出距离
    	for(i=0;i<N;i++)
    		printf("%5d",d[i]);
    	printf("\n");
    	//打印最短距离经过的节点
    	for(i=1;i<N;i++){
    		printf("v0->v%d:::",i);
    		for(j=1;j<N;j++)
    			printf("%5d",p[i][j]);
    		printf("\n");
    	}
    	getchar();
    }

    我们可以看下运行的结果

    运行结果

    是不是还不理解外层循环到底做了什么?

    v到底变了没有?

    让我们来调试一下:

    未标题-1

    未标题-2

    现在来看看下面的一个for(k)是干什么的。。

    未标题-3

    未标题-5

    未标题-6

    大功告成!OK。。。

  • 相关阅读:
    CCF NOI1079 合法C标识符
    CCF NOI1080 统计字符
    CCF NOI1076 进制转换
    CCF NOI1065 最小公倍数
    CCF NOI1139 高精度减法
    CCF NOI1138 高精度加法
    CCF NOI1115 找数
    CCF NOI1097 数列
    CCF NOI1089 高精度运算
    NUC1931 Problem D 区间素数【素数筛选】
  • 原文地址:https://www.cnblogs.com/shenerguang/p/2328619.html
Copyright © 2020-2023  润新知