动态规划之任意顶点间最短距离

来源:互联网 发布:什么是微观数据 编辑:程序博客网 时间:2024/06/03 13:33
A,动态规划思想:假设带权有向图G中的任意编号为(V1,V2,V3,...,Vn),如果 Vi到Vj的最短路径是d(i,j),那么对于路径上任一中间节点k,d(i,k)与d(k,j)都是最短路径。Vi到Vj的最短路径要么经过k,要么不经过k,就如同动态规划解矩阵连乘问题一样,我们只要从i到j枚举k,有j-i个选择,但是矩阵加括号后,其子问题之间不会有交点。对于图而言,如果不加限制d与d可能会有交集,因此我们这样处理:

动态规划之任意顶点间最短距离
上述就是下面将要介绍的floyd-warshall算法的思想。
B,算法原理:
1)算法中有两个数组path,A,其中A[i][j]代表Vi到Vj经过的路径的最小代价,path[i][j]表示Vi到Vj经过的中间节点k;
2)要计算A[i][j],就首先计算A[i][k]和A[k][j],其中A[i][k]和A[k][j]没有交点;
3)循环图中的每个节点,并先假设将每次循环的节点k作为图中任意两个节点最短路径之间的中间节点;
4)如果图中任意两个节点Vi到Vj经过k节点后代价更小,则使k作为Vi到Vj的中间节点,否则Vi到Vj不需要经过k;
5)直到遍历完每个节点(即每个节点都作为“桥”之后),算法结束。
下图为该算法处理四个节点的有向图的过程:

动态规划之任意顶点间最短距离
C,算法实现:
#include "iostream"
using namespace std;
typedef char VertexType;//定义邻接矩阵节点的类型
#define MAXIMUM 65535//无穷大
#define MAXVEX 50//图中最大节点数
typedef struct //定义邻接矩阵的数据结构
{
VertexType vexs[MAXVEX];
int edges[MAXVEX][MAXVEX];
int vexNum, adgeNum;//分别表示图中节点个数和边的条数
}AGraph;

int main()
{
void createAGraph(AGraph*);
void floydPath(int A[][MAXVEX], int path[][MAXVEX],int);
void printPath(int, int, int[][MAXVEX], AGraph *);
int A[MAXVEX][MAXVEX], path[MAXVEX][MAXVEX];
AGraph g;
createAGraph(&g);
for(int i = 0; i < g.vexNum; ++i)
for(int j = 0; j
{
path[i][j] = -1;
A[i][j] = g.edges[i][j];
}
floydPath(A, path, g.vexNum);
while(true)
{
int m,n;
cout<<"请输入任意两个顶点序号i,j:";
cin>>m>>n;
cout<<g.vexs[m]<<"->";
printPath(m, n, path, &g);
cout<<g.vexs[n]<<endl;
}

return 0;
}
//输出任意两点之间的最短路径
void printPath(int i, int j, int path[][MAXVEX], AGraph*g)
{
int k = path[i][j];
if(-1 == k)
return;
printPath(i, k, path, g);
cout<<g->vexs[k]<<"->";
printPath(k, j, path, g);

}
//Floyd算法求解任意顶点间的最短路径
void floydPath(int A[][MAXVEX], int path[][MAXVEX], intn)
{
for(int k = 0; k < n; ++k)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; ++j)
{
if(A[i][k] + A[k][j] < A[i][j])
{
A[i][j] = A[i][k] + A[k][j];
path[i][j] = k;
}
}
}

void createAGraph(AGraph *g)//创建图的邻接矩阵
{
int vNum, aNum;//分别代表要创建的图的节点数和边数
int start, end;//start->end表示节点start和end之间有一条边
int weight;//边的权重
cout<<"请输入图中节点的个数和边的条数:";
cin>>vNum>>aNum;
printf("\n请输入%d个节点的信息:", vNum);
//创建节点
for(int i = 0; i < vNum; ++i)
{
cin>>g->vexs[i];
}
cout<<"这里输出节点编号及其存储的节点信息"<<endl;
for(int k = 0; k < vNum; ++k)
cout<<k<<":"<<g->vexs[k]<<"";
cout<<endl;
//初始化边信息
for(int m = 0; m < vNum; ++m)
for(int n = 0; n < vNum; ++n)
{
if(m == n)
g->edges[m][n] = 0;
else
g->edges[m][n] = MAXIMUM;
}
//创建无向图的边信息
for(int j = 0; j < aNum; ++j)
{
cout<<"\n请输入第"<<j+1<<"条边的start和end节点和边的权值weight:";
cin>>start>>end>>weight;
g->edges[start][end] = weight;
}
//初始化vexNum和adgeNum
g->vexNum = vNum;
g->adgeNum = aNum;
}
运行结果:

动态规划之任意顶点间最短距离
D,算法复杂度
时间复杂度:Floyd算法求最短路径是有三层循环嵌套,时间复杂度为O(n^3)。

0 0