算法导论12--Dijkstra算法

一、目的

1.熟悉算法设计的基本思想
2.掌握最小生成树算法的思路

二、内容与设计思想

川西风光几枚,以下图片是川西路线图。张三是旅游爱好者,他从成都出发自驾到西藏江达。
请添加图片描述

1)从成都到江达的最短自驾路线是什么?可以用Dijkstra算法来求解。

#include<bits/stdc++.h>
using namespace std;
#define Infinity 65535
#define ERROR -1

int P[10000];
string A[33]={"成都","都江堰","汶川","映秀","雅安","理县",
			"日隆","马尔康","小金","泸定","康定","丹巴","金川",
			"新都桥","塔公","八美","雅江","道孚","炉霍","翁达",
			"A","B","壤塘","色达","甘孜","新龙","理塘",
			"马尼干戈","新路海","德格","白玉","巴塘","江达"}; 

typedef struct GNode
{
	int Nv;
	int Ne;
	int G[1000][1000];
	int Data[1000];
} MGraph;

typedef struct ENode
{
	int V1,V2;
	int Weight;
} Edge;

MGraph* CreateGraph(int VertexNum)
{
	int V,W;
	MGraph* Graph;
	
	Graph=new MGraph;
	Graph->Nv=VertexNum;
	Graph->Ne=0;
	
	for (V=0;V<Graph->Nv;V++)
	{
		for (W=0;W<Graph->Nv;W++)
		{
			Graph->G[V][W]=Infinity;
		}
	}
	
	return Graph;
}

void InsertEdge(MGraph* Graph,Edge* E)
{
	Graph->G[E->V1-Graph->Data[0]][E->V2-Graph->Data[0]]=E->Weight;
	Graph->G[E->V2-Graph->Data[0]][E->V1-Graph->Data[0]]=E->Weight;                         
}

MGraph* BuildGraph(MGraph* Graph)
{
	Edge* E;
	int V;
	int Nv,Ne,i;
	
	cin>>Nv>>Ne;
	
	Graph=CreateGraph(Nv);
	Graph->Ne=Ne;
	
	for (V=0;V<Nv;V++)
	{
//		cin>>Graph->Data[V];
		Graph->Data[V]=V;
	}
	
	if (Graph->Ne!=0)
	{
		E=new Edge;
		for (i=0;i<Graph->Ne;i++)
		{
			cin>>E->V1>>E->V2>>E->Weight;
			InsertEdge(Graph,E);
		}
	}
	cout<<endl;
	
	return Graph;
}

int FindMinDist(MGraph* Graph,int dist[],int collected[])
{
	int MinV,V;
	int MinDist=Infinity;
	
	for (V=0;V<Graph->Nv;V++)
	{
		if (collected[V]==false&&dist[V]<MinDist)
		{
			MinDist=dist[V];
			MinV=V;
		}
	}
	
	if (MinDist<Infinity)
	{
		return MinV;
	}
	else
	{
		return ERROR;
	}
}

bool Dijkstra(MGraph* Graph,int dist[],int path[],int S)
{
	int collected[100000];
	int V,W;
	
	for (V=0;V<Graph->Nv;V++)
	{
		dist[V]=Graph->G[S][V];
		if (dist[V]<Infinity)
		{
			path[V]=S;
		}
		else
		{
			path[V]=-1;
		}
		collected[V]=false;
	}
	
	dist[S]=0;
	collected[S]=true;
	
	while (1)
	{
		V=FindMinDist(Graph,dist,collected);
		if (V==ERROR)
		{
			break;
		}
		collected[V]=true;
		
		for (W=0;W<Graph->Nv;W++)
		{
			if (collected[W]==false&&Graph->G[V][W]<Infinity)
			{
				if (Graph->G[V][W]<0)
				{
					return false;
				}
				if (dist[V]+Graph->G[V][W]<dist[W])
				{
					dist[W]=dist[V]+Graph->G[V][W];
					path[W]=V;
				}
			}
		}
	}
	
	return true;
}

int FindPath(int path[],int V) 
{
	int k=0;
	while (V>=0)
	{
		P[k]=V;
		V=path[V];
		k++;
	}
	
	return k;
}

int main()
{
	MGraph* Graph;
	bool flag;
	int S,E,Total;
	int dist[100000],path[100000];
	
	S=0;
	E=32;
	Graph=BuildGraph(Graph);
	flag=Dijkstra(Graph,dist,path,S);
	
	if (flag==true)
	{
		cout<<A[S]<<"-->"<<A[E]<<";"<<dist[E]<<endl;
	}
	
	Total=FindPath(path,E);
	for (int i=Total-1;i>=0;i--)
	{
		cout<<A[P[i]]<<" ";
	}
	
	return 0;
}

2)张三把理塘列为必游之地。怎么规划路线,使得总行程最短?

#include<bits/stdc++.h>
using namespace std;
#define Infinity 65535
#define ERROR -1

int P[100000];
string A[33]={"成都","都江堰","汶川","映秀","雅安","理县",
			"日隆","马尔康","小金","泸定","康定","丹巴","金川",
			"新都桥","塔公","八美","雅江","道孚","炉霍","翁达",
			"A","B","壤塘","色达","甘孜","新龙","理塘",
			"马尼干戈","新路海","德格","白玉","巴塘","江达"}; 

typedef struct GNode
{
	int Nv;
	int Ne;
	int G[1000][1000];
	int Data[1000];
} MGraph;

typedef struct ENode
{
	int V1,V2;
	int Weight;
} Edge;

MGraph* CreateGraph(int VertexNum)
{
	int V,W;
	MGraph* Graph;
	
	Graph=new MGraph;
	Graph->Nv=VertexNum;
	Graph->Ne=0;
	
	for (V=0;V<Graph->Nv;V++)
	{
		for (W=0;W<Graph->Nv;W++)
		{
			Graph->G[V][W]=Infinity;
		}
	}
	
	return Graph;
}

void InsertEdge(MGraph* Graph,Edge* E)
{
	Graph->G[E->V1-Graph->Data[0]][E->V2-Graph->Data[0]]=E->Weight;
	Graph->G[E->V2-Graph->Data[0]][E->V1-Graph->Data[0]]=E->Weight;                         
}

MGraph* BuildGraph(MGraph* Graph)
{
	Edge* E;
	int V;
	int Nv,Ne,i;
	
	cin>>Nv>>Ne;
	
	Graph=CreateGraph(Nv);
	Graph->Ne=Ne;
	
	for (V=0;V<Nv;V++)
	{
//		cin>>Graph->Data[V];
		Graph->Data[V]=V;
	}
	
	if (Graph->Ne!=0)
	{
		E=new Edge;
		for (i=0;i<Graph->Ne;i++)
		{
			cin>>E->V1>>E->V2>>E->Weight;
			InsertEdge(Graph,E);
		}
	}
	cout<<endl;
	
	return Graph;
}

int FindMinDist(MGraph* Graph,int dist[],int collected[])
{
	int MinV,V;
	int MinDist=Infinity;
	
	for (V=0;V<Graph->Nv;V++)
	{
		if (collected[V]==false&&dist[V]<MinDist)
		{
			MinDist=dist[V];
			MinV=V;
		}
	}
	
	if (MinDist<Infinity)
	{
		return MinV;
	}
	else
	{
		return ERROR;
	}
}

bool Dijkstra(MGraph* Graph,int dist[],int path[],int S)
{
	int collected[100000];
	int V,W;
	
	for (V=0;V<Graph->Nv;V++)
	{
		dist[V]=Graph->G[S][V];
		if (dist[V]<Infinity)
		{
			path[V]=S;
		}
		else
		{
			path[V]=-1;
		}
		collected[V]=false;
	}
	
	dist[S]=0;
	collected[S]=true;
	
	while (1)
	{
		V=FindMinDist(Graph,dist,collected);
		if (V==ERROR)
		{
			break;
		}
		collected[V]=true;
		
		for (W=0;W<Graph->Nv;W++)
		{
			if (collected[W]==false&&Graph->G[V][W]<Infinity)
			{
				if (Graph->G[V][W]<0)
				{
					return false;
				}
				if (dist[V]+Graph->G[V][W]<dist[W])
				{
					dist[W]=dist[V]+Graph->G[V][W];
					path[W]=V;
				}
			}
		}
	}
	
	return true;
}

int FindPath(int path[],int V) 
{
	int k=0;
	while (V>=0)
	{
		P[k]=V;
		V=path[V];
		k++;
	}
	
	return k;
}

int main()
{
	MGraph* Graph;
	bool flag;
	int S,M,E,Total;
	int dist[100000],path[100000];
	
	S=0;
	M=26;
	E=32;
	
	Graph=BuildGraph(Graph);
	flag=Dijkstra(Graph,dist,path,S);
	if (flag==true)
	{
		cout<<A[S]<<"-->"<<A[M]<<";"<<dist[M]<<endl;
	}
	int Total1=FindPath(path,M);
	for (int i=Total1-1;i>=0;i--)
	{
		cout<<A[P[i]]<<" ";
	}
	cout<<endl;
	
	flag=Dijkstra(Graph,dist,path,M);
	if (flag==true)
	{
		cout<<A[M]<<"-->"<<A[E]<<";"<<dist[E]<<endl;
	}
	int Total2=FindPath(path,E);
	for (int i=Total2-1;i>=0;i--)
	{
		cout<<A[P[i]]<<" ";
	}
	
	return 0;
}

3)张三觉得理塘风景很美,道孚也不错,两个地方如果能够去一个地方的话就心满意足了。应该怎么安排行程使得总行程最短?

4)张三在规划线路的时候,发现不同路况行驶速度不一样。地图中粗的路径表示平均时速可以达到80公里每小时,而细的路径表示平均时速仅仅有每小时60公里每小时。那么用时最短的路径是哪一条?

#include<bits/stdc++.h>
using namespace std;
#define Infinity 65535
#define ERROR -1

int P[10000];
string A[33]={"成都","都江堰","汶川","映秀","雅安","理县",
			"日隆","马尔康","小金","泸定","康定","丹巴","金川",
			"新都桥","塔公","八美","雅江","道孚","炉霍","翁达",
			"A","B","壤塘","色达","甘孜","新龙","理塘",
			"马尼干戈","新路海","德格","白玉","巴塘","江达"}; 

typedef struct GNode
{
	int Nv;
	int Ne;
	double G[1000][1000];
	int Data[1000];
//	int T[1000][1000];
} MGraph;

typedef struct ENode
{
	int V1,V2;
	double Weight;
	int T;
} Edge;

MGraph* CreateGraph(int VertexNum)
{
	int V,W;
	MGraph* Graph;
	
	Graph=new MGraph;
	Graph->Nv=VertexNum;
	Graph->Ne=0;
	
	for (V=0;V<Graph->Nv;V++)
	{
		for (W=0;W<Graph->Nv;W++)
		{
			Graph->G[V][W]=Infinity;
		}
	}
	
	return Graph;
}

void InsertEdge(MGraph* Graph,Edge* E)
{
	if (E->T==0)
	{
		Graph->G[E->V1-Graph->Data[0]][E->V2-Graph->Data[0]]=E->Weight/60.0;
		Graph->G[E->V2-Graph->Data[0]][E->V1-Graph->Data[0]]=E->Weight/60.0;
	}
	else if (E->T==1)
	{
		Graph->G[E->V1-Graph->Data[0]][E->V2-Graph->Data[0]]=E->Weight/80.0;
		Graph->G[E->V2-Graph->Data[0]][E->V1-Graph->Data[0]]=E->Weight/80.0;
	}                
}

//void Time(MGraph* Graph)
//{
//	int V,W;
//	for (V=0;V<33;V++)
//	{
//		for (W=0;W<33;W++)
//		{
//			if (Graph->T[V][W]==0)
//			{
//				Graph->G[V][W]=Graph->G[V][W]/60;
//			}
//			else if (Graph->T[V][W]==1)
//			{
//				Graph->G[V][W]=Graph->G[V][W]/80;
//			}
//		}
//	}
//}

MGraph* BuildGraph(MGraph* Graph)
{
	Edge* E;
	int V;
	int Nv,Ne,i;
	
	cin>>Nv>>Ne;
	
	Graph=CreateGraph(Nv);
	Graph->Ne=Ne;
	
	for (V=0;V<Nv;V++)
	{
//		cin>>Graph->Data[V];
		Graph->Data[V]=V;
	}
	
	if (Graph->Ne!=0)
	{
		E=new Edge;
		for (i=0;i<Graph->Ne;i++)
		{
			cin>>E->V1>>E->V2>>E->Weight>>E->T;
			InsertEdge(Graph,E);
//			Time(Graph);
		}
	}
	cout<<endl;
	
	return Graph;
}

int FindMinDist(MGraph* Graph,double dist[],int collected[])
{
	int MinV,V;
	int MinDist=Infinity;
	
	for (V=0;V<Graph->Nv;V++)
	{
		if (collected[V]==false&&dist[V]<MinDist)
		{
			MinDist=dist[V];
			MinV=V;
		}
	}
	
	if (MinDist<Infinity)
	{
		return MinV;
	}
	else
	{
		return ERROR;
	}
}

bool Dijkstra(MGraph* Graph,double dist[],int path[],int S)
{
	int collected[100000];
	int V,W;
	
	for (V=0;V<Graph->Nv;V++)
	{
		dist[V]=Graph->G[S][V];
		if (dist[V]<Infinity)
		{
			path[V]=S;
		}
		else
		{
			path[V]=-1;
		}
		collected[V]=false;
	}
	
	dist[S]=0;
	collected[S]=true;
	
	while (1)
	{
		V=FindMinDist(Graph,dist,collected);
		if (V==ERROR)
		{
			break;
		}
		collected[V]=true;
		
		for (W=0;W<Graph->Nv;W++)
		{
			if (collected[W]==false&&Graph->G[V][W]<Infinity)
			{
				if (Graph->G[V][W]<0)
				{
					return false;
				}
				if (dist[V]+Graph->G[V][W]<dist[W])
				{
					dist[W]=dist[V]+Graph->G[V][W];
					path[W]=V;
				}
			}
		}
	}
	
	return true;
}

int FindPath(int path[],int V) 
{
	int k=0;
	while (V>=0)
	{
		P[k]=V;
		V=path[V];
		k++;
	}
	
	return k;
}

int main()
{
	MGraph* Graph;
	bool flag;
	int S,E,Total;
	int path[100000];
	double dist[100000];
	
	S=0;
	E=32;
	Graph=BuildGraph(Graph);
	flag=Dijkstra(Graph,dist,path,S);
	
	if (flag==true)
	{
		cout<<A[S]<<"-->"<<A[E]<<";"<<dist[E]<<endl;
	}
	
	Total=FindPath(path,E);
	for (int i=Total-1;i>=0;i--)
	{
		cout<<A[P[i]]<<" ";
	}
	
	return 0;
}

5)(思考题)考虑到Dijkstra算法仅仅从一段开始寻找路径,效率不高。李教授想到一个高招,就是同时从出发地和目的地进行搜索,扩展搜索节点,然后两个方向扩展的路径会在中途相遇,则拼接起来的路径就是最短路径。如何实现李教授这个想法?

三、使用环境

推荐使用C/C++集成编译环境。

四、实验过程

1、编写相关实验代码
2、写出算法的思路。
第二题分成两步,先由成都到理塘再从理塘到江达,用两次Dijkstra算法;
第三题即把1、2题的距离比较;
第四题再设置一个数组E->T,当值为0时代表细边,当值为1时代表粗边,然后把G[V][W]的值换算成时间再使用Dijkstra算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值