最近在看DP相关的知识, 遇到图的最短路径 重新看了一遍 ,自己写了的code 测试了一下 。
算法步骤:
a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。
b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
d.重复步骤b和c直到所有顶点都包含在S中
算法具体描述参考 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
/*
*
* int Dij_array[6][6] ={{ 0, 6, 3,999,999,999},
{6 , 0, 2, 5,999,999},
{3 , 2, 0, 3, 4,999},
{999, 5, 3, 0, 2, 3},
{999,999, 4, 2, 0, 5},
{999,999,999, 3, 5, 0}};
*
*
* */
void Dijkstra_demo(int a[6][6] ,int dim){
int row ,col, keyPath, nextRow;
keyPath = 0 ;
nextRow = 0 ;
int Flag[dim] ={1};
int minInEachRow[dim] ={};
int addVolume = 0;
for(row = 0; row< dim ;row++){
int minInRow = 999;
nextRow = 1;
Flag[row] = 1;
minInEachRow[0] = 3;//hard code here
// for(int i =0 ; i<6 ; i++){
// printf("flagbbb = %d \t ",Flag[i]);
// }
// printf("current row = %d \n ",row);
for(col = 1; col <dim ; col++){
if( (Flag[col]==0)&&(col != row ) &&( minInRow > a[row][col] )) {
minInRow = a[row][col] ;
nextRow = col;
}
}
// if(row == 0)keyPath = minInRow ;
keyPath = keyPath + minInRow ;
printf("keyPath 1 = %d \t",keyPath );
int tempKey =0;
int addVolumeIndex = 0;
for(int i = 1 ; i<6 ; i++){
if(Flag[i]==1) {
tempKey = a[i][0] + a[i][nextRow];
printf("ccctempKey = %d %d ,%d i = %d\t",tempKey,a[i][0],a[i][nextRow] , i );
if(tempKey < keyPath) {
keyPath = tempKey;
addVolume = a[i][nextRow];
}
}
}
printf("\n" );
minInEachRow[nextRow] = addVolume ;// recorder for print path
a[nextRow][0] = keyPath ;
//if(a[nextRow][0] != keyPath) PrintFlag[i]=2;
// for(int i = 0 ; i<6 ; i++){
//
//
// printf("a[i]= %d ",a[i][0] );
//
// }
//
// if(row == 0){
// keyPath = keyPath + minInRow ;
// }
// else{
// if(a[row][0] > keyPath)
// a[row][0] = keyPath;
// }
//
//
// int minInCol = 999; // skip a[0][0]
// for(int i =1 ; i<6 ; i++){
// if((Flag[i]==1) && (minInCol > a[i][0]) )minInCol= a[i][0];
//
// }
// if(row > 0){
// keyPath = minInRow + minInCol ;
// if(a[nextRow][0] > keyPath)
// a[nextRow][0] = keyPath;
//
// }
printf("nextRow = %d in currentRow = %d , minInRow =%d ,minInCol =%d \n",nextRow , row ,minInRow ,a[row][0]);
if(keyPath > 999 )break;
if(Flag[nextRow] == 0 )
row = nextRow -1; // for wil add one in next loop
// for(int i =0 ; i<6 ; i++){
// printf("flag = %d \t ",Flag[i]);
// }
printf("keyPath = %d ,row = %d \n\n", keyPath ,row);
printf("===========================\n");
if(nextRow == 5 ){
for(int i = 0 ;i < 6 ;i++){
printf(" %d <===" ,minInEachRow[i]);
}
printf("=========the KeyPath is %d= addVolume =%d=================\n" , keyPath ,a[0][0]);
printf("=========the Path is = 5 << ");
for(int i = 5 ;i >=0 ;i--){
if(a[i][0] == (keyPath -addVolume )){
printf(" %d <===" ,i);
keyPath = keyPath -addVolume ;
addVolume = minInEachRow[i];
}
}printf(" 0 .... end %d %d\n" ,keyPath , addVolume );
break ;
}
}
}
计算的步骤就是
1.从6x6的矩阵第一行找出最小的数值,记录出列号即要跳过去的行号 nextRow
2.在新的行内,标记行号Flag[row] 并且在本行内找 “行号没被标记过”的最小值 minInRow,记录出列号即要跳过去的行号,更新keypath
3.循环标记过的行 比较 (a[row][0] +a[row][nextRow]) 和keypath 。如果小于keypath ,就说明有比 keypath 更短的路径,更新后方在
a[row][0] 中, 并将增量addVolume 记录下来, 用来打印路径。
4 goto第二步
* int Dij_array[6][6] ={{ 0, 6, 3,999,999,999},
{6 , 0, 2, 5,999,999},
{3 , 2, 0, 3, 4,999},
{999, 5, 3, 0, 2, 3},
{999,999, 4, 2, 0, 5},
{999,999,999, 3, 5, 0}};
数据说明 999是不可到的意思,0是自己,a[row][0] 用来记录到本行的最短距离