求解最短路径,输入如下
7 7
0 9 7 2 -1 -1 -1
-1 0 -1 -1 5 -1 -1
-1 5 0 2 -1 -1 -1
-1 -1 4 0 -1 3 -1
-1 -1 -1 -1 0 -1 6
-1 3 -1 -1 11 0 9
-1 -1 -1 -1 -1 -1 0
第一行存储行列数
// ShortestRoute.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <malloc.h>
#include <stdlib.h>
#include <vector>
using namespace std;
float JudgeMin(float a,float b1,float b2)
{
if(b2<0)
return a;
else
{
if(a<0)
return b1+b2;
else
{
if(a<b1+b2)
return a;
else
return b1+b2;
}//else
} //else
}
void _tmain(int argc, _TCHAR* argv[])
{
int iNO = 0; // 循环次数
int iRow,iCol; // 矩阵行、列数
char m_file[] = "图3-10.txt";
typedef struct LIST{
float *fM; // 存储M值
int iCurPt; // 当前点
LIST* pChild;
LIST* pParent;
};
bool* blTransverse; // 标识点是否已经转变为P标号点
int iStart,iEnd; // 最短路径的起点、终点
bool blExit = false; // 判断循环是否退出
float** m_data; // 存储原始数据矩阵
int ptCur; // 当前循环计算的起点点号
LIST* listH = new LIST; // 头指针
LIST* listE; // 尾指针
// 读文件
FILE *fp;
if((fp = fopen(m_file,"r")) == NULL){
printf("can not open this file\n");
return;
};
fscanf(fp,"%d %d",&iRow,&iCol);
//动态定义原始数据
m_data = (float**)malloc(sizeof(m_data) * iRow);
for(int i = 0;i < iRow;i++)
m_data[i] = (float*)malloc(sizeof(m_data) * iCol);
listH->fM = new float[iRow - 1];
blTransverse = new bool[iRow - 1];
for(int i = 0;i < iRow;i++){
listH->fM[i] = -1.0;
blTransverse[i] = false;
}
int i = 0,j = 0;
while(!feof(fp)){
fscanf(fp, "%f", &m_data[i][j]);
j++;
if(j == iCol){
i++; j=0;
}
}
fclose(fp);
//选择最短路径的起点和终点
printf("Please input start point(>=1), iStart = ");
scanf("%d",&iStart);
printf("\nPlease input end point(<=7), iEnd = ");
scanf("%d",&iEnd);
listH->iCurPt = iStart;
listH->pParent = NULL;
listH->pChild = NULL;
listH->fM[iStart - 1] = 0.0;
blTransverse[iStart - 1] = true;
ptCur = iStart;
LIST* listCur = listH;
LIST* listChild;
while(!blExit){
blExit = true;
//对每一个点在循环之前,判断是否所有点都变为固定标号
for(int i = 0;i < iRow;i++){
if(!blTransverse[i]){
blExit = false;
break;
}
}
if(blExit) continue;
iNO++;
// 对于每一个顶点进行循环,计算以当前标记点到其它点之间的距离
for(int i = 0;i < iRow;i++){
if(!blTransverse[i]){ // 是否已经被遍历
float temp = JudgeMin(listCur->fM[i],listCur->fM[ptCur - 1],m_data[ptCur - 1][i]);
listCur->fM[i] = temp;
}
}
// 寻找最小值所对应的点号
bool blExist = false; // 下次循环是否存在点
float temp = 99999999999;
for(int i = 0;i < iRow;i++){
if(!blTransverse[i]){
if(temp > listCur->fM[i] && listCur->fM[i] > 0){
temp = listCur->fM[i];
ptCur = i + 1;
blExist = true;
}
}
}
// 若存在点,则分配空间;否则,退出循环
if(blExist){
listChild = new LIST;
}
else{
printf("Cannot arrive at some point\n");
break;
}
if(listChild){
listChild->pChild = NULL;
listChild->fM = new float[iRow - 1];
for(int i = 0;i < iRow;i++)
listChild->fM[i] = listCur->fM[i];
blTransverse[ptCur - 1] = true;
listChild->iCurPt = ptCur;
listChild->pParent = listCur;
listCur->pChild = listChild;
listCur = listCur->pChild;
}
}
// 确定链表的长度
LIST* pBake = listH;
int iLength = 0;
while(listH->pChild != NULL){
listH = listH->pChild;
iLength++;
}
listH = pBake;
listE = listCur;
if(listH->pChild == NULL) iLength = 1;
printf("循环次数是:%d;链表长度是:%d\n",iNO,iLength);
// 开始从后向前确定最短路径
float** m_dist = new float*[iLength];
for(int i = 0;i < iLength;i++)
m_dist[i] = new float[iRow];
int* ptCurList = new int[iLength];
int m = 0;
while(listH->pChild != NULL){
for(int n = 0;n < iRow;n++){
m_dist[m][n] = listH->fM[n];
}
ptCurList[m] = listH->iCurPt;
listH = listH->pChild;
m++;
}
listH = pBake;
vector <int> ptVect;
ptVect.push_back(iEnd);
ptCur = iEnd;
blExit = false;
// 首先判断终点是否有值,如果没有则表示无法到达
if(m_dist[iLength - 1][ptCur - 1] < 0){
printf("Cannot arrive at the end point\n");
system("pause");
return;
}
for(int i = iLength - 1;i >= 0;i--){
for(int j = iLength - 2;j >= 0;j--){
if(m_dist[i][ptCur - 1] < m_dist[j][ptCur - 1] && m_dist[j][ptCur - 1] > 0){
ptCur = ptCurList[i - 1]; // 这个是关键
ptVect.push_back(ptCur);
i = j;
j = iLength - 2;
}
if(m_dist[j][ptCur - 1] < 0){
ptCur = ptCurList[j + 1];
ptVect.push_back(ptCur);
}
}
}
ptVect.push_back(iStart);
// 输出路径
printf("最短路径是:\n");
for(int i = ptVect.size() - 1;i >= 0;i--){
printf("%d ",ptVect[i]);
if(i != 0) printf("-> ");
}
// 释放链表
while(listE->pParent != NULL){
LIST* temp = listE;
listE = listE->pParent;
listE->pChild = NULL;
delete temp;
}
system("pause");
}