地铁换乘-最短路径问题

网上看的一道题,自己用C++实现了一下,如有错误欢迎指正

#include <string>
#include <iostream>
using namespace std;
/************************************************************************/
/*地铁换乘 
描述:已知2条地铁线路,其中A为环线,B为东西向线路,线路都是双向的。经过的站点名分别如下,
两条线交叉的换乘点用T1、T2表示。编写程序,任意输入两个站点名称,输出乘坐地铁最少需要经过的
车站数量(含输入的起点和终点,换乘站点只计算一次)。
地铁线A(环线)经过车站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A14 A15 A16 A17 A18
地铁线B(直线)经过车站:B1 B2 B3 B4 B5 T1 B6 B7 B8 B9 B10 T2 B11 B12 B13 B14 B15
输入:输入两个不同的站名
输出:输出最少经过的站数,含输入的起点和终点,换乘站点只计算一次
输入样例:A1 A3
输出样例:3   */
/************************************************************************/
#define NODENUM 50
#define MAXWEIGHT 65535
typedef struct Node 
{
	bool flag;
	int weight;
}Matrix[NODENUM][NODENUM];


typedef struct MGraph 
{
	int arcnum;
	int vertexnum;
	Matrix adjmatrix;
}MGraph,*pMGraph;

typedef enum index{A1,A2,A3,A4,A5,A6,A7,A8,A9,T1,A10,A11,A12,A13,T2,A14,A15,A16,A17,A18,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15};
string str[]={"A1","A2","A3","A4","A5","A6","A7","A8","A9","T1","A10","A11","A12","A13","T2",
	"A14","A15","A16","A17","A18","B1","B2","B3","B4","B5","B6","B7","B8","B9","B10","B11","B12","B13","B14","B15"};
void CreateSubRailWay(pMGraph &mg)//n为站点的个数
{
	int n=sizeof(str)/sizeof(string);
	mg->vertexnum=n;
	for (int i=0;i<n;i++)
	{
		for (int j=0;j<n;j++)
		{
			mg->adjmatrix[i][j].weight=MAXWEIGHT;
		}
	}
	//对相邻的站点的权值进行赋值
	for (int i=A1;i<=A17;i++)//对环形路线进行赋值
	{
		mg->adjmatrix[i][(i+1)].weight=1;
		mg->adjmatrix[i+1][i].weight=1;
	}
	mg->adjmatrix[A18][A1].weight=1;
	mg->adjmatrix[A1][A18].weight=1;

	//对直线线路进行赋值
	for (int i=B1;i<=B4;i++)
	{
		mg->adjmatrix[i][i+1].weight=1;
		mg->adjmatrix[i+1][i].weight=1;
	}
	//B5T1 B6T1
	mg->adjmatrix[B5][T1].weight=1;
	mg->adjmatrix[T1][B5].weight=1;
	mg->adjmatrix[T1][B6].weight=1;
	mg->adjmatrix[B6][T1].weight=1;
	for (int i=B6;i<=B9;i++)
	{
		mg->adjmatrix[i][i+1].weight=1;
		mg->adjmatrix[i+1][i].weight=1;
	}
	//B10T2 B11T2
	mg->adjmatrix[B10][T2].weight=1;
	mg->adjmatrix[T2][B10].weight=1;
	mg->adjmatrix[T2][B11].weight=1;
	mg->adjmatrix[B11][T2].weight=1;
	for (int i=B11;i<=B14;i++)
	{
		mg->adjmatrix[i][i+1].weight=1;
		mg->adjmatrix[i+1][i].weight=1;
	}
	//查看矩阵是否正确(可注释掉)
	for (int k=0;k<n;k++)
	{
		for (int m=0;m<n;m++)
		{
			if (mg->adjmatrix[k][m].weight==MAXWEIGHT)
			{
				printf("%d ",0);
			}
			else
			{
				printf("%d ",mg->adjmatrix[k][m].weight);
			}

		}
		printf("\n");
	}
}

//使用Dijk算法求最短路径
int Path[NODENUM];//存放前一个结点
int ShortestPath[NODENUM];
bool used_dij[NODENUM];//表示已经求得最短路径的结点
int Dijk(pMGraph &mg,int startpos)
{
	//首先进行初始化
	int n=mg->vertexnum;
	for (int i=0;i<n;i++)
	{
		Path[i]=startpos;
		ShortestPath[i]=mg->adjmatrix[startpos][i].weight;
		used_dij[i]=false;
	}
	//对起始结点初始化
	ShortestPath[startpos]=0;
	used_dij[startpos]=true;
	Path[startpos]=startpos;
	for (int i=1;i<n;i++)//进行n-1次遍历
	{
		int min=MAXWEIGHT;
		int k;
		//先找出当前权值最小的点
		for (int j=0;j<n;j++)
		{
			if (used_dij[j]!=true && min>ShortestPath[j])
			{
				min=ShortestPath[j];
				k=j;
			}
		}
		//对最小点操作
		used_dij[k]=true;
		//更新
		for (int j=0;j<n;j++)
		{
			if (used_dij[j]==false && mg->adjmatrix[k][j].weight+min<ShortestPath[j])
			{
				ShortestPath[j]=min+mg->adjmatrix[k][j].weight;
				Path[j]=k;//记录它的前一个结点
			}
		}

	}
	return 0;
}


int main(int argc,char *argv[])
{
	pMGraph mg=new MGraph;
	CreateSubRailWay(mg);
	printf("请输入起点和终点,空格分隔\n");
	string start,end;
	cin>>start;
	cin>>end;
	//根据输入的站点寻找站点的索引
	int startpos,endpos;
	for (int i=0;i<sizeof(str)/sizeof(string);i++)
	{
		if (start==str[i])
		{
			startpos=i;
		}
		if (end==str[i])
		{
			endpos=i;
		}
	}
	Dijk(mg,startpos);
	//根据Dijk输出的最短路径和前一节点数组确定路径长度和路径经过的各点
	printf("最短路径经过的总的站点个数为:%d\n",ShortestPath[endpos]+1);
	int len=sizeof(str)/sizeof(string);
	int sitecount=0;
	int sites[sizeof(str)/sizeof(string)];	
	//经过的站点顺序为
	int now=endpos;
	while(now!=startpos)
	{
		sites[sitecount++]=now;
		now=Path[now];
	}
	sites[sitecount]=now;
	//进行逆序输出
	printf("经过的站点顺序依次是:");
	for(int i=0;i<=sitecount;i++)
	{
		cout<<str[sites[sitecount-i]]<<"->";
	}
	cout<<"end"<<endl;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值