动态规划之最短路径源代码
最短路径——dijkstra算法代码(c语言)
最短路径——dijkstra算法代码(c语⾔)最短路径问题看了王道的视频,感觉云⾥雾⾥的,所以写这个博客来加深理解。
(希望能在12点以前写完)()⼀、总体思想1.初始化三个辅助数组s[],dist[],path[]s[]:这个数组⽤来标记结点的访问与否,如果该结点被访问,则为1,如果该结点还没有访问,则为0;dist[]:这个数组⽤来记录当前从v到各个顶点的最短路径长度,算法的核⼼思想就是通过不断修改这个表实现; path[]:这个数组⽤来存放最短路径;2.遍历图,修改上⾯的各项数组,每次只找最短路径,直到遍历结束⼆、代码实现1void dijkstra(Graph G, int v)2 {3int s[G.vexnum];4int dist[G.vexnum];5int path[G.vexnum];6for(int i = 0; i < G.vexnum; i++)7 {8 s[i] = 0;9 dist[i] = G.edge[v][i];10if(G.edge[v][i] == max || G.edge[v][i] == 0)11 {12 path[i] = -1;13 }14else15 {16 path[i] = v;17 }18 s[v] = 1;19 }2021for(int i = 0; i < G.vexnum; i++)22 {23int min = max;24int u;25for(int j = 0; j < G.vexnum; j++)26 {27if(s[j] != 1 && dist[j] < min)28 {29 min = dist[j];30 u = j;31 }32 }33 s[u] = 1;34for(int j = 0; j < G.vexnum; j++)35 {36if(s[j] != 1 && dist[j] > dist[u] + G.edge[u][j])37 {38 dist[j] = dist[u] + G.edge[u][j];39 path[j] = u;40 }41 }42 }43 }三、代码解释先⾃⼰定义⼀个⽆穷⼤的值max#define max infdijkstra算法传⼊的两个参为图Graph G;起点结点 int v;⾸先我们需要三个辅助数组1int s[G.vexnum];//记录结点时是否被访问过,访问过为1,没有访问过为02int dist[G.vexnum];//记录当前的从v结点开始到各个结点的最短路径长度3int path[G.vexnum];//记录最短路径,存放的是该结点的上⼀个为最短路径的前驱结点初始化三个数组1for(int i = 0; i < G.vexnum; i++)2 {3 s[i] = 0;//⽬前每个结点均未被访问过,设为04 dist[i] = G.edge[v][i];//dist[]数组记录每个从v结点开到其他i结点边的长度(权值)5if(G.edge[v][i] == max || G.edge[v][i] == 0)6 {7 path[i] = -1;8 }//如果v到i不存在路径或者i就是v结点时,将path[i]设为-1,意为⽬前v结点不存在路径到i9else10 {11 path[i] = v;12 }//反之,若v到i存在路径,则v就是i的前驱结点,将path[i] = v13 s[v] = 1;//从遍历起点v开始,即已经访问过顶点s[v]=114 }开始遍历数组并且每次修改辅助数组以记录⽬前的情况,直⾄遍历结束1for(int i = 0; i < G.vexnum; i++)2 {3int min = max;//声明⼀个min = max⽤来每次记录这次遍历找到的最短路径的长度(权值)4int u;//声明u来记录这次历找到的最短路径的结点5for(int j = 0; j < G.vexnum; j++)//开始遍历找⽬前的最短路径6 {7if(s[j] != 1 && dist[j] < min)8 {9 min = dist[j];10 u = j;11 }//找出v到结点j的最短路径,并且记录下最短路径的结点u = j12 }13 s[u] = 1;//找到结点u,即已访问过u,s[u] = 114for(int j = 0; j < G.vexnum; j++)//开始遍历修改辅助数组的值15 {16if(s[j] != 1 && dist[j] > dist[u] + G.edge[u][j])17 {18 dist[j] = dist[u] + G.edge[u][j];19 path[j] = u;20 }//如果v→j的路径⽐v →u→j长,那么修改dist[j]的值为 dist[u] + G.edge[u][j],并且修改j的前驱结点为path[j] = u21 }22 }遍历结束后,数组dist[]就是存放了起点v开始到各个顶点的最短路径长度最短路径包含的结点就在path数组中例如我们得到如下的path[]数组1 path[0] = -1;//0到⾃⼰⽆前驱结点2 path[1] = 0;//1的前驱为结点0,0⽆前驱结点,即最短路径为0 →13 path[2] = 1;//2的前驱结为点1,1的前驱结点0,0⽆前驱结点,即最短路径为0 →1 →24 path[3] = 0;//3的前驱为结点0,0⽆前驱结点,即最短路径为0 →35 path[4] = 2;//4的前驱结为点2,2的前驱结为点1,1的前驱结点0,0⽆前驱结点,即最短路径为0 →1 →2 →4 dijkstra对于存在负权值的图不适⽤,明天再更新Floyd算法叭。
最短路径算法源程序代码
// 最大结 // 节点 // 若节点间 #include < stdio .h>#include < conio.h>#include < string .h> #defineJiedianNum 6 点数#define NameLenght 3 名字长度#define Infinity 10000 没有路径距离设定为 Infinity char*JiedianNameFile = "jiedianname.txt" ;// 图的顶点 -- 节点名char *JiedianPathFile = "jiedianpath.txt" ; // 边 -- 节点间的连接关系char *MinPathDataFile ="minpath.txt" ;// 最短路径数据/******************************************************* /* 从文件中读入结点数据*//* 函数参数:*//* char jiedian[][]: 存放节点名的数组*//* int *NodNum: 指针变量,指向存放节点个数的变量*//* 输入数据:文本数据文件:JiedianNameFile*//* 文件数据格式:*//* < 节点个数>*//* < 节点名>*//* 输出数据:指从该函数中带回到调用函数的数据,包括:*//* jiedian[][]-- 节点名称*//* NodeNum-- 节点名的个数*//* 返回值:数据读入是否成功的标志*//* 0-- 失败1-- 成功*//******************************************************* int InputJiedianNode( char jiedian[][NameLenght], int *NodeNum ){int i,n;FILE *fp;if (!(fp = fopen(JiedianNameFile, "r" ))){ printf( "节点数据文件不存在\n" );getch();return (0);}fscanf(fp, "%d" ,&n);if (!n){ printf( "文件中无节点数据!\n" );getch();return (0);}for (i= 0;i< n;i++ ) fscanf(fp, "%s" ,jiedian[i]);fclose(fp);*NodeNum =n;return (1);}I******************************************************* /* 从文件中读入最短路径数据*//* 函数参数:*//* int dist[][]: 节点间最短路径的值*//* int Path[][]: 节点间最短路径结点数据*//* int *NodNum: 指针变量,表示读入数据的多少*//* 输入数据:数据文件:MinPathDataFile*//* 文件数据格式:二进制数据,数据存放顺序:*//* < 节点个数n><n*n 个最短路径值><n*n 个结点值> *//* 输出数据:指从该函数中带回到调用函数的数据,包括:*//* jiedian[][]*//* Path[][]*/*//* 返回值:数据读入是否成功的标志*//* 0-- 失败1-- 成功*//******************************************************* int InputMinPath( int dist[][JiedianNum], intPath[][JiedianNum], int *NodeNum){int n;FILE *fp;if (!(fp = fopen(MinPathDataFile, "rb" ))){ printf( " 最小路径数据文件不存在!\n" );getch();return (0);}fread( &n,sizeof (int ),1,fp);fread(dist, sizeof (int ),n*n,fp);fread(Path, sizeof (int ),n*n,fp); fclose(fp);*NodeNum =n;return (1);}/******************************************************* /* 查找节点名*//* 函数参数:*//* char str[][]: 存放节点名的数组*//* int n :str 中数据的行数,即节点名的个数*//* char *p: 指针变量,表示需要查找的节点名*//* 输入数据:全部函数参数均为输入数据*//* 输出数据:返回值作为函数的输出数据*//* 查找成功:被查找的节点名在数组str 中的序号*/ /* 查找失败:-1,表示被查找的节点名未出现在数组中*//******************************************************* int search( char str[][NameLenght], int n,char*p){int i=0;while(i< n){ if (!strcmp(str[i],p)) return (i); i++;} return (- 1); }I*******************************************************/**//* 函数参数:计算节点间最短路径< 无>*//* 输入数据:文本数据文件:JiedianNameFile*/ /* */ /* */ /* */ /*文件数据格式:< 节点个数>< 节点名>文本数据文件:JiedianPathFile*/ /*文件数据格式:*//* < 边数>*//* < 结点名>< 节点名>< 边值> *//* 输出数据:数据文件:MinPathDataFile*//* 文件数据格式:二进制数据,数据存放顺序:*/ /* < 结点个数n><n*n 个最短路径值><n*n 个结点值> *//* 返回值:< 无>*//* 说明:文本数据文件中数据间用空格或换行符格开*//******************************************************* void shorttestpath(){int i,j,k,NodeNum,EgeNum,val;int arc[JiedianNum][JiedianNum];// 权值矩阵char jiedian[JiedianNum][NameLenght];// 结点int dist[JiedianNum][JiedianNum]; // 最短路径长度矩阵int Path[JiedianNum][JiedianNum];// 最短路径矩阵charjiedian1[NameLenght],jiedian2[NameLenght]JFILE *fp;/* -------------------------------------------------- *//* 算法步骤:*//* 1、读入结点数据*//* 2、邻接矩阵初始化:所有元素赋Infinity ,*//* 对角线元素赋0 *//* 3、读入结点间边的数据,转换为邻接矩阵的数据*//* 4、路径矩阵初始化,若arc[i][j]<Infinity ,*//* 则:at[i][j]=i 否则:Path[i][j]=-1 *//* 5、计算最短路径*//* 6、保存最小路径数据*//* -------------------------------------------------- */// -------- 初始化邻接矩阵if (!InputJiedianNode(jiedian, & NodeNum)) return ;else{for (i= 0;i< NodeNum;i ++){for (j =0;j< NodeNum;j ++)if(i== j) arc[i][j] =0; else arc[i][j]=Infinity;}printf( "%s\n" ,jiedian[i]);}}// ---- 读入结点间边的数据--------if (!(fp = fopen(JiedianPathFile, "r" ))) {printf( " 结点间边的数据文件不存在!!!\n" );getch(); return ;}fscanf(fp, "%d" ,& EgeNum);if (!EgeNum){printf( " 文件中无结点间边的数据!!!\n" );getch();return ; }for (k=0;k< EgeNum;k ++ ){fscanf(fp, "%s" ,jiedian1);fscanf(fp, "%s" ,jiedian2);fscanf(fp, "%d" ,&val);i=search(jiedian,NodeNum,jiedian1); j=search(jiedian,NodeNum,jiedian2); arc[i][j]=arc[j][i] =val;}fclose(fp);// -------- 路径矩阵初始化for (i= 0;i< NodeNum;i ++)for (j = 0;j < NodeNum;j ++){if ((arc[i][j] < Infinity) && (i!= j))Path[i][j] =i;else Path[i][j] =- 1;}// 初始化最短路径长度矩阵dist[][]for (i= 0;i< NodeNum;i ++ )for (j = 0;j< NodeNum;j ++)dist[i][j] =arc[i][j];// 弗罗伊德算法for (k=0;k< NodeNum;k ++)for (i= 0;i< NodeNum;i ++ )for (j = 0;j < NodeNum;j ++)if (dist[i][k] +dist[k][j] < dist[i][j]) {dist[i][j] =dist[i][k] + dist[k][j];Path[i][j] =Path[k][j];}// -------- 保存城市间最短路径的信息if (!(fp = fopen(MinPathDataFile, "wb" ))){printf( " 打不开文件%s !!!\n" ,MinPathDataFile); getch(); return ;}fwrite( & NodeNum, sizeof (int ),1,fp);fwrite(dist, sizeof (int ),NodeNum *NodeNum,fp) fwrite(Path, sizeof (int ),NodeNum *NodeNum,f p);fclose(fp);return ;}/******************************************************* /* 求一个节点到其它节点的最短路径*//* 函数参数:< 无>*//* 输入数据:文本数据文件:JiedianNameFile *//* 数据文件:MinPathDataFile*/*//* 输出数据:*//* 指定节点到其它所有节点的最短路径值和路径*//* (屏幕显式)*//* 返回值:< 无>*//******************************************************* void One_To_Other_Path(){int i,j,k,NodeNum,StartNode;char jiedian[JiedianNum][NameLenght];// 结点int dist[JiedianNum][JiedianNum];// 最短路径长度矩阵int Path[JiedianNum][JiedianNum];// 最短路径矩阵int top,PathStack[JiedianNum]; char jiedian1[NameLenght]; FILE *fp;/*数组中获得/*中结点间路径/*并放入栈中,/* *//* 算法步骤:*//* 1、输入结点数据*//* 2、输入最小路径数据*//* 3、输入起点节点名称,并确定其正确性*//* 方法:调用查找函数,若返回值>=0则正确*//* 4、依次求起点节点到其它节点的最短路径*//* 方法:根据两节点的序号i,j在dist*/最短路径值。
C语言迪杰斯特拉实现最短路径算法
C语言迪杰斯特拉实现最短路径算法迪杰斯特拉(Dijkstra)算法是一种用于在加权图中寻找从起点到终点的最短路径的算法。
它使用贪心算法的原理,每次选择权重最小的边进行扩展,直到找到终点或者无法扩展为止。
下面是C语言中迪杰斯特拉算法的实现。
```c#include <stdio.h>#include <stdbool.h>//定义图的最大节点数#define MAX_NODES 100//定义无穷大的距离#define INFINITY 9999//自定义图的结构体typedef structint distance[MAX_NODES][MAX_NODES]; // 节点间的距离int numNodes; // 节点数} Graph;//初始化图void initGraph(Graph* graph)int i, j;//设置所有节点之间的初始距离为无穷大for (i = 0; i < MAX_NODES; i++)for (j = 0; j < MAX_NODES; j++)graph->distance[i][j] = INFINITY;}}graph->numNodes = 0;//添加边到图void addEdge(Graph* graph, int source, int destination, int weight)graph->distance[source][destination] = weight;//打印最短路径void printShortestPath(int* parent, int node)if (parent[node] == -1)printf("%d ", node);return;}printShortestPath(parent, parent[node]);printf("%d ", node);//执行迪杰斯特拉算法void dijkstra(Graph* graph, int source, int destination) int i, j;//存储起点到各个节点的最短距离int dist[MAX_NODES];//存储当前节点的父节点int parent[MAX_NODES];//存储已访问的节点bool visited[MAX_NODES];//初始化所有节点的距离和父节点for (i = 0; i < graph->numNodes; i++)dist[i] = INFINITY;parent[i] = -1;visited[i] = false;}//设置起点的距离为0dist[source] = 0;//寻找最短路径for (i = 0; i < graph->numNodes - 1; i++)int minDist = INFINITY;int minNode = -1;//选择距离最小的节点作为当前节点for (j = 0; j < graph->numNodes; j++)if (!visited[j] && dist[j] < minDist)minDist = dist[j];minNode = j;}}//标记当前节点为已访问visited[minNode] = true;//更新最短距离和父节点for (j = 0; j < graph->numNodes; j++)if (!visited[j] && (dist[minNode] + graph->distance[minNode][j]) < dist[j])dist[j] = dist[minNode] + graph->distance[minNode][j];parent[j] = minNode;}}}//打印最短路径及距离printf("Shortest Path: ");printShortestPath(parent, destination);printf("\nShortest Distance: %d\n", dist[destination]); int maiGraph graph;int numNodes, numEdges, source, destination, weight;int i;//初始化图initGraph(&graph);//输入节点数和边数printf("Enter the number of nodes: ");scanf("%d", &numNodes);printf("Enter the number of edges: ");scanf("%d", &numEdges);graph.numNodes = numNodes;//输入边的信息for (i = 0; i < numEdges; i++)printf("Enter source, destination, and weight for edge %d: ", i + 1);scanf("%d %d %d", &source, &destination, &weight);addEdge(&graph, source, destination, weight);}//输入起点和终点printf("Enter the source node: ");scanf("%d", &source);printf("Enter the destination node: ");scanf("%d", &destination);//执行迪杰斯特拉算法dijkstra(&graph, source, destination);return 0;```上述代码中,我们首先定义了一个图的结构体,里面包括节点间的距离矩阵和节点数。
动态规划实现最短路径问题
动态规划实现最短路径问题⼀、设计最短路径的动态规划算法 <算法导论>中⼀般将设计动态规划算法归纳为下⾯⼏个步骤: 1)分析最优解的结构 2)递归定义最优解的值 3)⾃底向上计算最优解的值 4)从计算的最优解的值上⾯构建出最优解⼆、最短路径的结构 从最优解的结构开始分析(我们假设没有权值为负的路径),对于图G<V,E>的所有结点对最短路径的问题,我们能知道⼀条最短路径的⼦路径都是最短路径。
假设⽤邻接矩阵W=w(ij)来表⽰输⼊带权图,考虑从结点i到结点j的⼀条最短路径p,如果p最多有m(m为有限值)条边。
若i=j,则p的权值为0⽽且不包含其他边。
若i ≠ j,可以将i到j的路径转换为i -> k、k->j。
三、⼀个给定的图 1)给定⼀个有向图 2)我们可以给出这个有向图的邻接矩阵四、C++实现1 #include <iostream>2 #include<fstream>3 #include<sstream>4 #include<vector>5 #include<string>6using namespace std;7const int Max_Num = 100;89 typedef struct Point {10int n; //点的个数11double p[Max_Num];12double q[Max_Num];13int root[Max_Num][Max_Num];14double w[Max_Num][Max_Num];15double e[Max_Num][Max_Num];16 }Point;1718 vector<Point> points;19 vector<string> res;20 vector<int> num;2122void file_read();23void createPoint();24void optimalBST();25void printRoot(Point P);26void printOptimalBST(int i, int j, int r, Point P, ofstream &fileWrite);27 template <class Type>28 Type stringToNum(const string& str) {29 istringstream iss(str);30 Type num;31 iss >> num;32 iss.str("");33return num;34 }3536void file_read() {37string str2, str1 = "", result;38 ifstream fileRead("in.dat");39if (fileRead.is_open()) {40while (getline(fileRead, str2, '\n')) {41if (str2.find("") != -1) {42 str1.append(str2 + "");43 }44else {45 num.push_back(stringToNum<int>(str2));46if (str1 != "") {47 res.push_back(str1);48 }49 str1 = "";50 }51 }52 res.push_back(str1);53 fileRead.close();54 }55 }5657void createPoint() {58string temp;59 Point P;60for (int i = 0; i < res.size(); i++) {61 vector<string> temp_str; //存放按照空格分开后的数字62int n = num[i];63 stringstream input(res[i]);64while (input >> temp) {65 temp_str.push_back(temp);66 }67 P.n = n;68for(int k = 0; k<=n; k++) P.p[k] = stringToNum<double>(temp_str[k]);69for(int k = n + 1; k<temp_str.size(); k++) P.q[k-(n+1)] = stringToNum<double>(temp_str[k]);70 points.push_back(P);71 }72 }7374//根据书上的伪代码:接收概率列表p1....pn和q0.....qn以及规模n作为输⼊计算出e和root75void optimalBST(){76 Point P;77for(int i = 0; i<res.size(); i++) {78 vector<string> temp_str; //存放按照空格分开后的数字79int n = num[i];80string temp;81 stringstream input(res[i]);82while (input >> temp) {83 temp_str.push_back(temp);84 }85 P.n = n;8687for(int k = 0; k<=n; k++) P.p[k] = stringToNum<double>(temp_str[k]);88for(int k = n + 1; k<temp_str.size(); k++) P.q[k-(n+1)] = stringToNum<double>(temp_str[k]); 8990//初始化只包括虚拟键的⼦树91for (int i = 1;i <= P.n + 1;++i){92 P.w[i][i-1] = P.q[i-1];93 P.e[i][i-1] = P.q[i-1];94 }95//由下到上,由左到右逐步计算96for (int len = 1;len <= P.n;++len){97for (int i = 1;i <= P.n - len + 1;++i){98int j = i + len - 1;99 P.e[i][j] = Max_Num;100 P.w[i][j] = P.w[i][j-1] + P.p[j] + P.q[j];101//求取最⼩代价的⼦树的根102for (int r = i;r <= j;++r)103 {104double temp = P.e[i][r-1] + P.e[r+1][j] + P.w[i][j];105if (temp < P.e[i][j])106 {107 P.e[i][j] = temp;108 P.root[i][j] = r;109 }110 }111 }112 }113 points.push_back(P);114 }115 }116117void printOptimalBST(int i, int j, int r, Point P, ofstream &fileWrite){118int root_node = P.root[i][j];//⼦树根节点119if (root_node == P.root[1][P.n]){120//输出整棵树的根121 fileWrite << "k" << root_node << "是根" << endl;122 printOptimalBST(i, root_node - 1, root_node, P, fileWrite);123 printOptimalBST(root_node +1 , j, root_node, P, fileWrite);124return;125 }126127if (j < i - 1){128return;129 }else if (j == i - 1){//遇到虚拟键130if (j < r)131 fileWrite << "d" << j << "是" << "k" << r << "的左孩⼦" << endl;132else133 fileWrite << "d" << j << "是" << "k" << r << "的右孩⼦" << endl;134return;135 }136else{//遇到内部结点137if (root_node < r)138 fileWrite << "k" << root_node << "是" << "k" << r << "的左孩⼦" << endl; 139else140 fileWrite << "k" << root_node << "是" << "k" << r << "的右孩⼦" << endl; 141 }142 printOptimalBST(i, root_node - 1, root_node, P, fileWrite);143 printOptimalBST(root_node + 1, j, root_node, P, fileWrite);144 }145146//输出最优⼆叉查找树所有⼦树的根147void printRoot(Point P){148 cout << "各⼦树的根:" << endl;149for (int i = 1;i <= P.n;++i){150for (int j = 1;j <= P.n;++j){151 cout << P.root[i][j] << "";152 }153 cout << endl;154 }155 cout << endl;156 }157158int main(){159 file_read();160 optimalBST();161 ofstream fileWrite("out.dat");162 Point P ;163for(int i = 0; i<points.size(); i++) {164 P = points[i];165 printRoot(P);166 printOptimalBST(1,P.n,-1, P, fileWrite);167 }168 fileWrite.clear();169return0;170 } 上述代码是将给定的邻接矩阵从⽂件中读取 然后根据输⼊的邻接矩阵求出最短路径。
Python中的最短路径算法详解
Python中的最短路径算法详解Python是一门高效的编程语言,其强大的算法库包含了许多经典的算法,比如最短路径算法。
最短路径算法是图论中的一个经典问题,它的目的是在图中寻找从一个指定顶点到另一个指定顶点的最短路径,即边权重之和最小的路径。
最短路径算法有很多种,其中比较常见的有Dijkstra算法、Bellman-Ford算法和Floyd算法。
接下来我将分别介绍这3种算法的原理和Python实现。
1. Dijkstra算法Dijkstra算法是最短路径算法中比较经典的一种,它采用贪心策略,通过每次选取当前离源点最近的节点来不断扩展路径,直至到达终点。
它的基本思路如下:步骤1:定义源点s到其它节点的距离数组dist[],每当找到一条从源点可以到达的路径,就比较这条路径的长度和已知的最短路径长度,如果路径更短,就替换当前的最短路径长度,并更新终点节点的前一个节点。
步骤2:标记源点s为已经访问过的节点,将该节点入队,并在队列中取出此时距离源点最近的节点v。
步骤3:对所有与节点v相邻的节点w,计算出新的距离dist[s][w],如果dist[s][w]小于已知的最短距离,就更新最短距离,并将节点w加入队列中。
步骤4:重复步骤2和步骤3,直到队列为空。
Dijkstra算法的时间复杂度为O(n^2),其中n为节点数,因此它适用于稠密图。
下面是Python中Dijkstra算法的代码实现:```pythonimport heapqdef dijkstra(graph, start):#初始距离和前驱节点dist = {start: 0}previous = {start: None}#所有未确定最短距离的节点放入堆中heap = [(0, start)]heapq.heapify(heap)while heap:(d, u) = heapq.heappop(heap)#如果已经处理过该节点,则直接跳过if u in dist and d > dist[u]:continuefor v, w in graph[u].items():#计算新的距离newdist = dist[u] + w#如果新距离比原距离更小,则更新距离和前驱节点if v not in dist or newdist < dist[v]:dist[v] = newdistprevious[v] = uheapq.heappush(heap, (newdist, v))return (dist, previous)#测试graph = {'A': {"B": 2, "D": 4},'B': {"C": 3, "D": 1},'C': {"D": 1, "E": 5},'D': {"E": 1},'E': {}}dist, prev = dijkstra(graph, 'A')print(dist) # {'A': 0, 'B': 2, 'D': 3, 'C': 5, 'E': 4}print(prev) # {'A': None, 'B': 'A', 'D': 'B', 'C': 'B', 'E': 'D'}```2. Bellman-Ford算法Bellman-Ford算法是一种适用于有向图的单源最短路径算法,它可以处理有负权边的情况,但是不能处理负环的情况。
c语言最短路径的迪杰斯特拉算法
c语言最短路径的迪杰斯特拉算法Dijkstra的算法是一种用于查找图中两个节点之间最短路径的算法。
这个算法可以应用于有向图和无向图,但是它假设所有的边都有正权值,并且不包含负权值的边。
以下是一个简单的C语言实现:c复制代码#include<stdio.h>#define INF 99999#define V 5 // 顶点的数量void printSolution(int dist[]);void dijkstra(int graph[V][V], int src);int main() {int graph[V][V] = { { 0, 4, 0, 0, 0 }, { 4, 0, 8, 11, 7 },{ 0, 8, 0, 10, 4 },{ 0, 11, 10, 0, 2 },{ 0, 7, 4, 2, 0 } };dijkstra(graph, 0);return0;}void dijkstra(int graph[V][V], int src) { int dist[V];int i, j;for (i = 0; i < V; i++) {dist[i] = INF;}dist[src] = 0;for (i = 0; i < V - 1; i++) {int u = -1;for (j = 0; j < V; j++) {if (dist[j] > INF) continue;if (u == -1 || dist[j] < dist[u]) u = j;}if (u == -1) return;for (j = 0; j < V; j++) {if (graph[u][j] && dist[u] != INF && dist[u] + graph[u][j] < dist[j]) {dist[j] = dist[u] + graph[u][j];}}}printSolution(dist);}void printSolution(int dist[]) {printf("Vertex Distance from Source\n"); for (int i = 0; i < V; i++) {printf("%d \t\t %d\n", i, dist[i]);}}这个代码实现了一个基本的Dijkstra算法。
Python实现迪杰斯特拉算法并生成最短路径的示例代码
Python实现迪杰斯特拉算法并⽣成最短路径的⽰例代码def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价print("Start Dijstra Path……")path=[]#s-d的最短路径n=len(network)#邻接矩阵维度,即节点个数fmax=999w=[[0 for i in range(n)]for j in range(n)]#邻接矩阵转化成维度矩阵,即0→maxbook=[0 for i in range(n)]#是否已经是最⼩的标记列表dis=[fmax for i in range(n)]#s到其他节点的最⼩距离book[s-1]=1#节点编号从1开始,列表序号从0开始midpath=[-1 for i in range(n)]#上⼀跳列表for i in range(n):for j in range(n):if network[i][j]!=0:w[i][j]=network[i][j]#0→maxelse:w[i][j]=fmaxif i==s-1 and network[i][j]!=0:#直连的节点最⼩距离就是network[i][j]dis[j]=network[i][j]for i in range(n-1):#n-1次遍历,除了s节点min=fmaxfor j in range(n):if book[j]==0 and dis[j]<min:#如果未遍历且距离最⼩min=dis[j]u=jbook[u]=1for v in range(n):#u直连的节点遍历⼀遍if dis[v]>dis[u]+w[u][v]:dis[v]=dis[u]+w[u][v]midpath[v]=u+1#上⼀跳更新j=d-1#j是序号path.append(d)#因为存储的是上⼀跳,所以先加⼊⽬的节点d,最后倒置while(midpath[j]!=-1):path.append(midpath[j])j=midpath[j]-1path.append(s)path.reverse()#倒置列表print(path)#print(midpath)print(dis)#return pathnetwork=[[0,1,0,2,0,0],[1,0,2,4,3,0],[0,2,0,0,1,4],[2,4,0,0,6,0],[0,3,1,6,0,2],[0,0,4,0,2,0]]Dijkstra(network,1,6)以上就是Python实现迪杰斯特拉算法并⽣成最短路径的⽰例代码的详细内容,更多关于Python实现迪杰斯特拉算法的资料请关注其它相关⽂章!。
Floyd算法求解最短路径问题(完整程序代码)
引言在图论中经常会遇到这样的问题,在一个有向图里求出任意两个节点之间的最短距离。
当节点之间的权值是正值的时候,我们可以采用Dijkstra算法,用贪心策略加于解决。
但当节点之间的权值有负数的时候,Dijkstra就行不通了,这里介绍另外一种算法—Floyd最短路径算法。
对于任意图,选择存储结构存储图并实现FLOYD算法求解最短路经。
将问题分解,分解为两方面。
一是对于任意图的存储问题,第二个是实现FLOYD算法求解最短路经。
首先对于图的创建选择合适的存储结构进行存储,对于合适的存储结构可以简化程序。
本实验采用邻接矩阵存储。
然后是实现FLOYD算法求解最短路经,在FLOYD算法中路径的长度即是图中两定点间边的权值,FLOYD算法要求输出任意两个顶点间的最短路径,而且经过的顶点也要输出。
考虑到问题的特殊性,采用一个二维数组和一个三维数组进行存储。
二维数组存储最短路径,三维数组存储路径经过的顶点,在进行适当的算法后对这两个数组进行输出即可。
通过问题的分解,逐个解决,事先所要求的程序。
最短路径算法问题是计算机科学、运筹学、地理信息系统和交通诱导、导航系统等领域研究的一个热点。
传统的最短路径算法主要有Floyd算法和Dijkstra算法。
Floyd算法用于计算所有结点之间的最短路径。
Dijkstra算法则用于计算一个结点到其他所有结点的最短路径。
Dijkstra算法是已经证明的能得出最短路径的最优解,但它的效率是一个很大的问题。
对于具有n个结点的一个图,计算一个结点到图中其余结点最短路径的算法时间复杂度为O(n2)。
对于一座大中型城市,地理结点数目可能达到几万个到几十万个,计算最短路径的时间开销将是非常巨大的。
本文根据吴一民老师的建议,分析当前存在的各种求最短路径的算法,提出一种新的基于层次图的最短路径算法,即将一个平面图划分若干子图,子图抽象为一个高层图。
最短路径的计算首先在高层图中进行,缩小了最短路径的查找范围,降低了最短路径计算的时间开销。
动态规划:最短路径问题及程序
最短路径问题下图给出了一个地图,地图中每个顶点代表一个城市,两个城市间的连线代表道路,连线上的数值代表道路长度。
现在,我们想从城市a到达城市E。
怎样走才能使得路径最短,最短路径的长度是多少?设DiS[x]为城市x到城市E的最短路径长度(x表示任意一个城市);map[i,j]表示i,j两个城市间的距离,若map[i,j]=0,则两个城市不通;我们可以使用回溯法来计算DiS[x]:varS:未访问的城市集合;function search(who{x}):integer; {求城市who与城市E的最短距离} beginif Who=E Then Search←0 {找到目标城市}Else beginmin←maxint;{初始化最短路径为最大} for i 取遍所有城市 Doif(map[Who,i]>0{有路})and(i S{未访问})then beginS←S-[i];{置访问标志}j←map[Who,i]+ search(i); {累加城市E至城市Who的路径长度}S←S+[i]; {回溯后,恢复城市i未访问状态}if j<min Then min←j; {如果最短则记下}end;{then}search←min;{返回最短路径长度}End;{else}End;{search}beginS←除E外的所有城市;Dis[a]←search(a);{计算最短路径长度}输出Dis[a];end.{main}这个程序的效率如何呢?我们可以看到,每次除了已经访问过的城市外,其他城市都要访问,所以时间复杂度为O(n!),这是一个“指数级”的算法。
那么,还有没有效率更高的解题方法呢?首先,我们来观察上述算法。
在求b1到E 的最短路径的时候,先求出从C2到E 的最短路径;而在求从b2刭E 的最短路径的时候,又求了一遍从C2刭E 的最短路径。
也就是说,从C2到E 的最短路径求了两遍。
同样可以发现,在求从Cl 、C2刭E 的最短路径的过程中,从Dl 到E 的最短路径也被求了两遍。
最短路径源码
m_ipPolyline = null;
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
#endregion
#region Private Function
INetElements ipNetElements = ipNetwork as INetElements;
int intCount = m_ipPoints.PointCount;
//定义一个边线旗数组
IEdgeFlag[] pEdgeFlagList = new EdgeFlagClass[intCount];
IGeoDataset ipGeoDataset;
ILayer ipLayer ;
IFeatureLayer ipFeatureLayer;
IEnvelope ipEnvelope, ipMaxEnvelope ;
double dblSearchTol;
INetworkCollection ipNetworkCollection = FeatureDataset as INetworkCollection;
INetWeight ipNetWeight = ipNetSchema.get_WeightByName(WeightName);
INetSolverWeights ipNetSolverWeights = ipTraceFlowSolver as INetSolverWeights;
using System;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
动态规划求最短路径的两种方法
动态规划1.最短路线问题解(1):将上图该画成下图:记a (1,2)=4,a(1,3)=5,依次类推,表示每个点和值的关系。
逆序递推方程:⎪⎩⎪⎨⎧==+++=0)6(61,2,3,4,5)}1(1),({min )(s f k k s k f k u k s k d k uk s k fAB 1B 2C 1 C 2C 3 C 4D 1D 2 D 3E 1 E 2F4523 6 8 7 75845348435 6 2 314 31234 5 6 789 101112134523 6 8 7 7584534 8435 6 2 314 3如图各状态:逆序递推,找出上一个状态到下一阶段的最小路径值。
例如,当K=4时,状态 它们到F 点需经过中途 点E ,需一一分析从E 到 F 的最短路:先说从D1到F 的最短路 有两种选择:经过 E1, E2, 比较最短。
这说明由 D1 到F 的最短距离为7,其路径为AB 1B 2C 1 C 2C 3 C 4D 1 D 2 D 3E 1 E 2F4523 6 87 75845348435 62 31 4 3第1阶段 第2阶段 第3阶段 第4阶段 第5阶段状态 1状态 2状态3状态 4状态 5状态 6)}(),(),(),(m in{)(252141511414E f E D d E f E D d D f ++=.7}35,43min{=++=.11F E D →→},,{3214D D D S =a=[0,4,5,inf,inf,inf,inf,inf,inf,inf,inf,inf,inf 4,0,inf,2,3,6,inf,inf,inf,inf,inf,inf,inf 5,inf,0,inf,8,7,7,inf,inf,inf,inf,inf,inf inf,2,inf,0,inf,inf,inf,5,8,inf,inf,inf,inf inf,3,8,inf,0,inf,inf,4,5,inf,inf,inf,inf inf,6,7,inf,inf,0,inf,inf,3,4,inf,inf,inf inf,inf,7,inf,inf,inf,0,inf,8,4,inf,inf,inf inf,inf,5,4,inf,inf,inf,0,inf,inf,3,5,inf inf,inf,inf,8,5,3,8,inf,0,inf,6,2,inf inf,inf,inf,inf,inf,4,4,inf,inf,0,1,3,inf inf,inf,inf,inf,inf,inf,inf,3,6,1,0,inf,4 inf,inf,inf,inf,inf,inf,inf,5,2,3,inf,0,3 inf,inf,inf,inf,inf,inf,inf,inf,inf,inf,4,3,0]; s8=min(a(8,11)+a(11,13),a(8,12)+a(12,13)); s9=min(a(9,11)+a(11,13),a(9,12)+a(12,13)); s10=min(a(10,11)+a(11,13),a(10,12)+a(12,13)); s4=min(a(4,8)+s8,a(4,9)+s9); s5=min(a(5,8)+s8,a(5,9)+s9); s6=min(a(6,9)+s9,a(6,10)+s10); s7=min(a(7,9)+s9,a(7,10)+s10); s2=[a(2,4)+s4,a(2,5)+s5,a(2,6)+s6]; s2=min(s2);s3=[a(3,5)+s5,a(3,6)+s6,a(3,7)+s7]; s3=min(s3);s1=min(a(1,2)+s2,a(1,3)+s3)运行结果为:s8 = 7 s9 = 5 s10 = 5 s4 = 12 s5 = 10 s6 = 8 s7 = 9 s2 =13s3 = 15 s1 = 17结果分析:s 表示每个点到终点的最短距离,那么最短路程为17。
单源最短路径c语言代码
单源最短路径c语言代码以下是Dijkstra算法的C语言代码实现,用于求解单源最短路径:```。
#include <stdio.h>。
#include <limits.h>。
#define V 6 // 图中顶点数。
//定义一个宏,用于查找尚未处理的最短路径的节点。
#define minDistance(dist, visited) \。
({ int min = INT_MAX, index; \。
for (int i = 0; i < V; i++) \。
if (!visited[i] && dist[i] <= min) \。
min = dist[i], index = i; \。
index; })。
void dijkstra(int graph[V][V], int src) 。
int dist[V]; // 存储从源点到各顶点的距离。
bool visited[V]; // 标记顶点是否被处理。
for (int i = 0; i < V; i++) 。
dist[i] = INT_MAX;。
visited[i] = false;。
}。
dist[src] = 0;。
for (int i = 0; i < V - 1; i++) 。
int u = minDistance(dist, visited);。
visited[u] = true;。
for (int j = 0; j < V; j++) 。
if (!visited[j] && graph[u][j] && dist[u] != INT_MAX &&。
dist[u] + graph[u][j] < dist[j])。
dist[j] = dist[u] + graph[u][j];。
}。
}。
printf("顶点距离源点的距离\n");。
最短路径算法源码(VB)
最短路径算法源码(VB)最短路径查询程序,速度特快,3万节点,35000条路全部遍历,只需1秒。
现将最短路径的思路告诉大家,希望大家在优化,并用不同语言编制,我正在学delphi,准备用delphi做成库,本例以由拓扑关系的arc/info 文件为数据源。
其中a1,b1,c1是以fnode排序生成的数组,a1对应fnode,b1对应tnode,c1对应length,同样a2,b2,c2,是以tnode 生成的数组。
Indexa1是对应某一起点与其相连的终点的个数,indexb1时对应某一终点与其相连的起点的个数,即其拓扑关系。
Public Function shortpath(startno As Integer, endno As Integer) As Single以开始点,结束点为参数。
Dim result() As SingleDim result1 As Integer定义结果点Dim s1 As SingleDim min As SingleDim ii, i, j, aa As IntegerDim yc() As BooleanDim ycd() As BooleanDim rs1() As SingleDim no() As IntegerDim nopoint As IntegerReDim yc(1 To maxno) As BooleanReDim ycd(1 To maxno) As BooleanReDim rs1(1 To maxno) As SingleReDim result(1 To 2, 1 To maxno) As Single定义结果,其中result(1,maxno)为结果点,result(2,maxno)为结果长度。
For i = 1 To maxno// maxno为网中最大的节点数。
yc(i) = False //标记已经查过的点。
ycd(i) = False //标记已经作结果点用过的点rs1(i) = 1E+38 //假设从起点到任一点的距离都为无穷大Next ill = startno //设置开始点。
动态规划解决旅行商问题附代码.docx
1.问题基本描述:求一个旅行商经过N个城市最后回到出发点的最短路径.即,在一个无向带权图的邻接矩阵中,求一个最短环包括所有顶点.2.解法:1)动态规划:假设从顶点i出发,令d(i,V’)表示从顶点i出发经过V’中各个顶点一次且仅一次,最后回到出发点i的最短路径的长度,开始时,V’=V-{i},于是,旅行商问题的动态规划函数为:d(i,V’) = min{c ik + d(k,V’-{k})} (k∈V’) 1)d(k,{}) = c ki (k ≠ i)2)简单来说,就是用递归表达:从出发点0到1号点,假设1是第一个,则剩下的路程就是从1经过剩下的点最后回到0点的最短路径. 所以当V’为空的时候, d(k,{}) = c ki (k ≠ i), 找的是最后一个点到0点的距离.递归求解1之后,再继续求V’之中剩下的点,最后找出min.如果按照这个思想直接做,对于每一个i都要递归剩下的V中所有的点,所以这样的时间复杂度就近似于N!,其中有很多重复的工作.可以从小的集合到大的集合算,并存入一个二维数组,这样当加入一个节点时,就可以用到之前的结果,如四个点的情况:动态填表:表中元素代表第i个节点经过V集合中的点最后到0点的最短值.如果有多个值,取其中最小的一个.这样一共循环(2^(N-1)-1)*(N-1)次,就把时间复杂度缩小到O(N*2)的级别.核心伪代码如下:{for (i =1;i<n;i++) //初始化第0列d[i][0]=c[i][0];for( j=1;j<2^(N-1)-1;j++)for(i=1 ; i<n ;i++){if(子集Vj中不包含i){对Vj中的每个元素k,计算d[i][Vj] = min{c[i][k] + d[k][{Vj-k}] | 每一个k∈Vj};}}对V[2^(n-1)-1]中的每个元素k,计算:d[0][2^(n-1)-1] = min{c[0][k] + d[k][2^(n-1)-2]};输出最短路径:d[0][2^(n-1)-1];}。
dijkstra最短路径算法代码
Dijkstra最短路径算法代码简介Dijkstra最短路径算法是一种用于求解图的单源最短路径问题的经典算法。
该算法以荷兰计算机科学家Edsger W. Dijkstra的名字命名,是非常高效的算法之一。
本文将详细介绍Dijkstra最短路径算法的原理和实现。
算法原理Dijkstra最短路径算法的核心思想是通过不断更新起始点到其他各顶点的距离,逐步扩展路径长度最短的顶点。
具体步骤如下: 1. 创建一个集合S,用于保存已经找到最短路径的顶点。
初始化时,将起始顶点加入S,并将起始顶点到自身的距离设为0,其他顶点的距离设为正无穷大。
2. 从集合S中选取一个顶点v,计算起始顶点到v相邻顶点u的距离。
如果这个距离小于目前已知的起始顶点到u的距离,则更新起始顶点到u的距离为这个距离。
3. 重复步骤2,直到集合S包含了所有顶点,或者找到了起始顶点到目标顶点的最短路径。
4. 返回最短路径结果。
算法实现使用Python语言可以比较方便地实现Dijkstra最短路径算法。
下面是一个简单的示例代码:def dijkstra(graph, start):# 初始化起始点到各顶点的距离distance = {vertex: float('inf') for vertex in graph}distance[start] = 0# 循环遍历所有顶点while graph:# 找出距离最小的顶点min_vertex = Nonefor vertex in graph:if min_vertex is None or distance[vertex] < distance[min_vertex]:min_vertex = vertex# 更新最小顶点周围的距离for neighbor, weight in graph[min_vertex].items():new_distance = distance[min_vertex] + weightif distance[neighbor] > new_distance:distance[neighbor] = new_distance# 将处理过的顶点移出图del graph[min_vertex]return distance示例和解析为了更好地理解Dijkstra最短路径算法,我们将通过一个图例来演示算法的运行过程。
最短路径算法floyd代码
最短路径算法floyd代码1.引言1.1 概述最短路径算法是图论中一个重要的问题,它的目标是找到两个节点之间最短的路径。
在实际生活中,最短路径算法被广泛应用于交通规划、物流配送、通信网络等领域。
针对不同类型的图,有不同的最短路径算法可供选择,其中Floyd算法是一种被广泛使用的算法之一。
Floyd算法是一种动态规划算法,它通过逐步优化图中各个节点之间的最短路径长度来求解最短路径。
其基本思想是通过计算任意两个节点之间的中间节点,以确定最短路径的中间节点集合。
通过反复迭代更新中间节点集合,最终可以得到节点之间的最短路径长度。
本文将介绍Floyd算法的原理和实现代码。
首先,我们将详细解释Floyd算法的原理,包括其计算最短路径的思路和步骤。
接着,我们将给出Floyd算法的代码实现,通过具体的编程示例来展示算法的具体实现过程和运行结果。
本文的目的是帮助读者了解Floyd算法,并通过实例代码帮助读者理解算法的具体实现步骤。
读者可以通过学习和实践运用Floyd算法,为实际问题寻找最短路径提供一种有效的解决方案。
此外,本文还将总结Floyd 算法的优缺点,以及对该算法在实际应用中的一些考虑和限制。
通过阅读本文并实践代码,读者将能够更好地理解Floyd算法的原理和实现方法,并在实际问题中灵活运用该算法来解决最短路径问题。
无论是对于图论的研究者还是对于应用场景中的实际需求,本文都将提供一些有价值的参考和启示。
在接下来的章节中,我们将逐步介绍Floyd算法的详细原理和代码实现。
让我们一起开始这段有趣的学习之旅吧!文章结构(Article Structure)本篇文章主要围绕最短路径算法Floyd展开讨论,按照以下结构进行阐述。
1. 引言1.1 概述:对最短路径算法的背景和应用进行简要介绍,强调其在网络通信、路线规划和图论等领域的重要性。
1.2 文章结构:本节内容。
1.3 目的:明确本文旨在通过介绍Floyd算法的原理和代码实现,帮助读者理解和应用该算法。
最短路径C++代码
#include <iostream.h>#define INF 32767#include<iomanip.h>#include<stdlib.h>const int maxvex=100;//单源最短路径void dijkstra(int cost[][maxvex],int n,int v){int ds[maxvex],p[maxvex];int s[maxvex];int min,i,j,u,w;for (i=0;i<n;i++){ds[i]=cost[v][i];//距离初始化s[i]=0; //S[ ]置空if (cost[v][i]<INF)//路径初始化p[i]=v;elsep[i]=-1;}s[v]=1;p[v]=0;//源点编号V放入S中for (i=0;i<n;i++)//循环直到所有顶点的最短路径都求出{min=INF;u=-1;for (j=0;j<n;j++)//选取不在S中且具有最小距离的顶点Uif(s[j]==0&&ds[j]<min){u=j;min=ds[j];}if (u!=-1)//找到最小距离的顶点U{s[u]=1;//将顶点U加入S中for (j=0;j<n;j++)//修改不在S中的顶点的距离if (s[j]==0)if (cost[u][j]<INF &&ds[u]+cost[u][j]<ds[j]){ds[j]=ds[u]+cost[u][j];p[j]=u;}}}cout<<setw(2)<<"\n 单源最短路径:\n";for (i=0;i<n;i++)//输出最短路径的长度,路径逆序输出{if (i!=v){cout<<""<<v<<"->"<<i<<":";if (s[i]==1){cout<<setw(2)<<"路径长度为"<<setw(2)<<ds[i]<<"";w=i;cout<<setw(2)<<"路径逆序为";while(w!=v)//一直加溯到初始顶点{cout<<w<<",";w=p[w];}cout<<w<<endl;}elsecout<<setw(2)<<"不存在路径"<<endl;}}}//单目标void danmubiao(int cost[][maxvex],int v,int n){int ds[maxvex],p[maxvex];int s[maxvex];int min,i,j,u,w;for (i=0;i<n;i++){ds[i]=cost[v][i]; //距离初始化s[i]=0; //S[ ]置空if (cost[v][i]<INF)//路径初始化p[i]=v;elsep[i]=-1;}s[v]=1;p[v]=0; //源点编号V放入S中for (i=0;i<n;i++) //循环直到所有顶点的最短路径都求出{min=INF;u=-1;for (j=0;j<n;j++)if(s[j]==0&&ds[j]<min) //选取不在S中且具有最小距离的顶点U{u=j;min=ds[j];}if (u!=-1) //找到最小距离的顶点U{s[u]=1; //将顶点U加入S中for (j=0;j<n;j++)//修改不在S中的顶点的距离if (s[j]==0)if (cost[u][j]<INF &&ds[u]+cost[u][j]<ds[j]){ds[j]=ds[u]+cost[u][j];p[j]=u;}}}cout<<setw(2)<<"\n 单目标最短路径:\n";for (i=0;i<n;i++)//输出最短路径的长度,路径逆序输出{if (i!=v){cout<<""<<i<<"->"<<v<<":";if (s[i]==1){cout<<setw(2)<<"路径长度为"<<setw(2)<<ds[i]<<"";w=i;cout<<setw(2)<<"路径顺序为";while(w!=v) //一直加溯到初始顶点{cout<<w<<",";w=p[w];}cout<<w<<endl;}elsecout<<"不存在路径"<<endl;}}}//单顶点void dandingdian(int cost[][maxvex],int a,int b){int G[maxvex][maxvex],p[maxvex][maxvex];int i,j,k,w;for (i=0;i<6;i++) //置初值for (j=0;j<6;j++){G[i][j]=cost[i][j];p[i][j]=-1;}for (k=0;k<0;k++){for (i=0;i<6;i++)for (j=0;j<6;j++)if (G[i][j]>G[i][k]+G[k][j]){G[i][j]=G[i][k]+G[k][j];p[i][j]=k;}}if(a!=b){cout<<setw(2)<<""<<a<<"->"<<b<<":";if (G[a][b]==INF){if(a!=b)cout<<setw(2)<<"不存在路径"<<endl;}else{ cout<<setw(2)<<"路径长度为"<<setw(3)<<G[a][b]<<"";cout<<setw(2)<<"路径为"<<a<<"";w=p[a][b];while (w!=-1){cout<<w<<"";w=p[w][b];}cout<<b<<endl;}}}//所有顶点对间void floyed(int cost[][maxvex],int n){int G[maxvex][maxvex],p[maxvex][maxvex];int i,j,k,w;for (i=0;i<n;i++)//置初值for (j=0;j<n;j++){G[i][j]=cost[i][j];p[i][j]=-1;}for (k=0;k<n;k++){for (i=0;i<n;i++)for (j=0;j<n;j++)if (G[i][j]>G[i][k]+G[k][j]){G[i][j]=G[i][k]+G[k][j];p[i][j]=k;}}cout<<setw(2)<<"\n 所有顶点对间最短路径:\n";for (i=0;i<n;i++)/*输出最短路径*/for (j=0;j<n;j++)if(i!=j){cout<<""<<i<<"->"<<j<<":";if (G[i][j]==INF){if(i!=j)cout<<setw(2)<<"不存在路径"<<endl;}else{cout<<setw(2)<<"路径长度为"<<setw(3)<<G[i][j]<<" ";cout<<setw(2)<<"路径为"<<i<<" ";w=p[i][j];while (w!=-1){cout<<w<<" ";w=p[w][j];}cout<<j<<endl;}}}void main(){int cost[6][maxvex]={{0,20,18, 18,15,INF},{20,0,26,INF,28,INF},{18,26,0,20,INF,INF },{18,INF,20,0,18,18},{15,28,INF,18,0,INF},{INF,INF,INF,18,INF,0}};cout<<" 最短路径"<<endl;cout<<" ============ "<<endl;cout<<" 1.单源最短路径"<<endl;cout<<" 2.单目标最短路径"<<endl;cout<<" 3.单顶点对间最短路径"<<endl;cout<<" 4.所有顶点对间最短路径"<<endl;cout<<" 请选择(1~4,0: 退出) ";int x;cin>>x;if (x==0) exit(0);else if (x==1){int a1;cout<<" 输入单源点:";cin>>a1;dijkstra(cost,6,a1);}//单源else if (x==2){int a2;cout<<" 输入单目标点:";cin>>a2;danmubiao(cost,a2,6);}//单目标else if (x==3){int a,b;cout<<" 输入两个顶点:";cin>>a>>b;dandingdian(cost,a,b);//单顶点对间}else if(x==4) floyed(cost,6);//所有顶点对间}。
动态规划所有点对的最短距离
例如,对右图中 的有向图,应用 Dijkstra算法计算从源 顶点1到其它顶点间 最短路径的过程列在 下页的表中。
s:
11 111
distan由ce源: 点1到0 顶1点0 5的50路径30为:601->4->3->5
path:
01 413
5
方法一:重复调用Dijkstra算法n次
• 可轮流以每一个顶点为源点,重复调用狄克斯 特拉算法函数Dijkstra() n次,即可求得所有顶
最近的点v3加入S。更新
②
相应信息。
③
④
s:
1 1 01 1 0
dist:
0 10 50 30 960
path: -1 1 4 1 4 3
26
①
第五步,将S外距离S
最近的点v5加入S。更新
②
⑤
相应信息。
③
④
s:
1 1 1 1 01
dist:
0 10 50 30 60
path: -1 1 4 1 3
①
②
s:
1 01 0 0 0
dist:
0 10 6∞0 30 100
path: -1 1 -1 21 1
24
①
第三步,将S外距离S
最近的点v4加入S。更新
②
相应信息。
④
s:
1 1 0 01 0
dist:
0 10 5600 30 19000
path: -1 1 2 41 1 4
25
①
第四步,将S外距离S
初始时,S中仅含有源点。设u是G的某一个 顶点,把从源点到u且中间只经过S中顶点的路称 为从源到u的特殊路径,并用数组distance记录当 前每个顶点所对应的最短特殊路径长度。 Dijkstra算法每次从V-S中取出具有最短特殊路长 度的顶点u,将u添加到S中,同时对数组distance 作必要的修改。一旦S包含了所有V中顶点, distance就记录了从源到所有其它顶点之间的最 短路径长度。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态规划之最短路径问题源代码
#include "stdio.h"
#include "conio.h"
#define n 16 /*图的顶点数*/
#define k 7 /*图的段数*/
#define l 30
#define MAX 100
typedef int NodeNumber;/*节点编号*/
typedef int CostType;/*成本值类型*/
CostType cost[n][n];
NodeNumber path[k];
NodeNumber cur=-1;
void creategraph(CostType *cost[n][n]) /*创建图的成本矩阵*/ {
int i,j,x,y,value;
for(i=0;i<n;i++)
for(j=0;j<n;j++) cost[i][j]=0;
printf("\nEnter the cost of graph:\n");
for(i=0;i<l;i++)
{
scanf("%d,%d,%d",&x,&y,&value);
cost[x][y]=value;
}
}
void outgraph(CostType *cost[n][n]) /*输出图的成本矩阵*/ {
int i,j;
printf("Print the cost of graph:\n");
for(i=0;i<n;i++)
{
for(j=0;j<n;j++) printf("%2d",cost[i][j]);
printf("\n");
}
}
/*使用向前递推算法求多段图的最短路径*/
void FPath(CostType *cost[n][n],NodeNumber *path[k]) {
int i,j,leng,temp,v[n],d[n];
for(i=0;i<n;i++) v[i]=0;
for(i=n-2;i>=0;i--)
{ leng=MAX;
for(j=i+1;j<=n-1;j++)
if(cost[i][j]>0 && (cost[i][j]+v[j])<leng)
{
leng=cost[i][j]+v[j];temp=j;
}
v[i]=leng;
d[i]=temp;
}
path[0]=0;
path[k-1]=n-1;
for(i=1;i<=k-2;i++) path[i]=d[path[i-1]]; }
/*输出最短路径序列*/
void outpath(NodeNumber *path[k])
{
int i;
printf("\nPrint the shortest treet:\n");
for(i=0;i<k;i++) printf("%3d",path[i]); }
main()
{
NodeNumber m,t;
creategraph(&cost);
outgraph(&cost);
FPath(&cost,&path);
outpath(&path);
}。