算法设计与应用实训-城市公交站点及换乘方案设计

1、任务内容
城市公共交通站点,站点之间的道路,及道路长度实际构成数学意义上的无向加权图。现请设计实现一个算法,求任意两站点间最短路径距离且输出该最短路径上的每个站点,然后给一个乘车换乘方案。
算法设计与应用实训-城市公交站点及换乘方案设计_第1张图片

2、需求分析
(1)显示站点信息:输入某个站点,程序显示停靠该站点的公交线路。
(2)显示公交信息:输入某个公交线路,程序显示该线路所经过的站点。
(3)查询出行方案:输入起始站和终点站,程序给出最短的路线,同时给出公交乘车及换乘的方案。

3、程序设计
(1)数据结构:

struct Point //站点
{
	int no;  //公交站点编号 
	char board[5];  // 站牌:该站有哪几路公交车经过 
};
struct MatGraph  //图的邻接矩阵类型 
{
	int edges[MAXV][MAXV];  //邻接矩阵
	int n,e;  //顶点数、边数 
	Point poi[MAXV];  //站点信息 
};

创建一个无向不带权图。其中,用邻接矩阵来存储站点样图中的路径信息;每个站点用一个数组来记录有哪几路公交车经过,若公交1路经过站点1,则poi[0].board[0]=1,若不经过则为0。
(2)功能实现:
①显示站点信息:
输入某个站点,程序遍历该站点的board数组,若board[i]=1,则说明公交线路i-1停靠该站点,将该线路输出。
②显示公交信息:
程序遍历该公交线路n的poi数组,若poi[i].board[n-1]=1,则说明公交线路i-1停靠该站点,将该站点输出。
③查询出行方案:
无向图存储完毕后,调用Floyd算法,用两个矩阵D[][]、P[][]记录每两个站点间的最短路径和中转点。输入起始站a和终点站b,记录当前站点now为起始站存储位a-1,记录下一站next为a到b的第一个中转点P[a-1][b-1]。比较now和next站点的board数组,如果这两个站点的board[i]都为1,即两个站点有相同公交线路,则乘坐该线路向前。记录下当前乘坐的线路j。之后进入循环,更新当前站now为next,更新下一站next为新的中转点即P[now][b-1]。继续比较两个站点是否有相同线路。比较中,如果当前乘坐的线路与之前记录的线路j不同,则视为换乘。继续该循环直到下一站next为终点站存储位b-1,出行方案显示完成。

4、遗留及待优化问题
(1)邻接矩阵存储线路信息,图的边数少,浪费大量内存空间,若使用邻接表形式则会更加节省空间。
(2)使用普通数组存储公交车信息,浪费内存空间。可使用bfs或dfs等算法降低空间开销。
(3)无法做到查询最少换乘方案的功能。

完整代码

//2019-2020学年第二学期 算法设计与应用实训

#include
#include
#include
#define INF 9999
#define MAXV 25 
using namespace std;

struct Point //站点
{
	int no;  //公交站点编号 
	int board[5];  // 站牌:该站有哪几路公交车经过 
};
struct MatGraph  //图的邻接矩阵类型 
{
	int edges[MAXV][MAXV];  //邻接矩阵
	int n,e;  //顶点数、边数 
	Point poi[MAXV];  //站点信息 
};

void CreateMat(MatGraph &g)  //图的创建 
{
	int i,j;
	int A[MAXV][MAXV]=  //邻接矩阵 
	{
		{0,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{1,0,1,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,1,0,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,1,0,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,1,INF,INF,0,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,1,INF,0,INF,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,1,INF,0,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,1,0,1,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,1,INF,1,0,1,INF,1,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,1,0,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,1,INF,INF,0,INF,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,0,INF,INF,1,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,INF,0,INF,INF,1,1,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,0,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,0,INF,INF,INF,1,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,0,INF,INF,INF,1,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,INF,0,INF,INF,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,0,1,INF,INF,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,1,0,INF,INF,1,1,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,INF,0,1,INF,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,0,INF,INF,INF,1},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,0,INF,INF,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,INF,0,1,INF},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,0,1},
		{INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,INF,1,INF,INF,1,0}
	};
	g.n=MAXV;g.e=26;  //边和点的数量 
	for(i=0;i<g.n;i++)
	{
		g.poi[i].no=i+1;  //站点编号赋值 
		for(j=0;j<5;j++)
			g.poi[i].board[j]=0;  //站牌初始化为空 
		for(j=0;j<g.n;j++)
			g.edges[i][j]=A[i][j];
	}
	g.poi[0].board[0]=1;  //站牌:该站点有某路公交车经过 
	g.poi[1].board[0]=1;g.poi[1].board[1]=1;
	g.poi[2].board[0]=1;
	g.poi[3].board[0]=1;
	g.poi[4].board[1]=1;
	g.poi[5].board[0]=1;
	g.poi[6].board[1]=1;
	g.poi[7].board[0]=1;g.poi[7].board[1]=1;
	g.poi[8].board[0]=1;g.poi[8].board[1]=1;g.poi[8].board[2]=1;
	g.poi[9].board[2]=1;
	g.poi[10].board[0]=1;
	g.poi[11].board[2]=1;
	g.poi[12].board[1]=1;g.poi[12].board[4]=1;
	g.poi[13].board[0]=1;
	g.poi[14].board[2]=1;
	g.poi[15].board[4]=1;
	g.poi[16].board[1]=1;
	g.poi[17].board[3]=1;
	g.poi[18].board[2]=1;g.poi[18].board[3]=1;
	g.poi[19].board[4]=1;
	g.poi[20].board[4]=1;
	g.poi[21].board[2]=1;
	g.poi[22].board[3]=1;
	g.poi[23].board[3]=1;
	g.poi[24].board[3]=1;g.poi[24].board[4]=1;
	
}

void main1(MatGraph g)  //显示站点信息 
{
	int number;
	cout<<"请输入想要显示的站点序号(1-25):";
	cin>>number;
	cout<<"站点"<<number<<"经过的公交线路为:";
	for(int i=0;i<5;i++)
		if(g.poi[number-1].board[i]==1) cout<<"公交"<<i+1<<"路 "; 
	cout<<endl;
}

void main2(MatGraph g)  //显示公交信息
{
	int number;
	cout<<"请输入想要显示的公交线路(1-5):";
	cin>>number;
	cout<<"公交"<<number<<"路途经的站点有:";
	for(int i=0;i<MAXV;i++)
	{
		if(g.poi[i].board[number-1]==1)
			cout<<"站点"<<i+1<<" ";
	} 
	cout<<endl;
} 

void Floyd(MatGraph g,int D[MAXV][MAXV],int P[MAXV][MAXV])  //Floyd算法 
{
	int i,j,k;
	for(i=0;i<g.n;i++)
		for(j=0;j<g.n;j++)
		{
			D[i][j]=g.edges[i][j];  //记录最短路径 
			P[i][j]=j;  //记录最短路径的第一个中转点 
		}
	for(i=0;i<g.n;i++)  //i为新增中转点 
		for(j=0;j<g.n;j++)
			for(k=0;k<g.n;k++)
				if(D[j][k]>(D[j][i]+D[i][k]))  //如果经过i中转点,j到k的路径变短 
				{
					D[j][k]=(D[j][i]+D[i][k]);  //更新j到k的最短路径 
					P[j][k]=P[j][i];  //更新该路径的第一个中转点为i 
				}
}

void main3(MatGraph g,int D[MAXV][MAXV],int P[MAXV][MAXV])  //查询出行方案 
{
	int a,b,i,j;
	cout<<"请输入起始站(1-25):";
	cin>>a;
	cout<<"请输入终点站(1-25):";
	cin>>b;
	cout<<"站点"<<a<<"到站点"<<b<<"的最短出行方案为:";
	int now=a-1;  //当前站为a 
	int next=P[a-1][b-1];  //下一站为a到b的第一个中转点 
	cout<<"站点"<<a;
	for(i=0;i<5;i++)
		if(g.poi[now].board[i]==1&&g.poi[next].board[i]==1)  //如果当前站和下一站的站牌都有某一公交线路,即两站间有某公交连通 
		{
			cout<<"(乘坐公交"<<i+1<<"路)" ;
			j=i;  //记录下当前乘坐的公交 
			break;
		}
	while(next!=b-1) //直到下一站为终点站,循环结束 
	{
		cout<<"-->站点"<<next+1;
		now=next;  //当前站更新 
		next=P[now][b-1];  //下一站更新为本站到终点站的第一个中转点 
        for(i=0;i<5;i++)
	    	if(g.poi[now].board[i]==1&&g.poi[next].board[i]==1)  //继续寻找连通两站的公交 
			{
				if(i!=j)  //如果该公交i与之前乘坐的公交j不同,则换乘 
				{
					cout<<"(换乘公交"<<i+1<<"路)" ;
					j=i;
				}
				break;
			}	
	}
	cout<<"-->站点"<<b<<endl;
}

int main()
{
	MatGraph map;
	CreateMat(map);	
	int D[MAXV][MAXV],P[MAXV][MAXV];
	Floyd(map,D,P);
	int choose;
	while(1)
	{ 
		cout<<"                                           "<<endl;
		cout<<"  ---------------------------------------- "<<endl;
		cout<<" |                 通讯录                 |"<<endl; 
		cout<<" |                                        |"<<endl;
		cout<<" |             1.显示站点信息             |"<<endl;
		cout<<" |                                        |"<<endl;
		cout<<" |             2.显示公交信息             |"<<endl;
    	cout<<" |                                        |"<<endl;
		cout<<" |             3.查询出行方案             |"<<endl;
		cout<<" |                                        |"<<endl;
		cout<<" |             0.退出                     |"<<endl;
		cout<<" |                                        |"<<endl;
        cout<<"  ---------------------------------------- "<<endl;
		cout<<"请选择:";
                                                                                leap0:
    	cin>>choose;
    	if(choose<0||choose>3)
    	{
	    	cout<<"请输入0-3的数字:";
	    	goto leap0;
	    }
		else
		     switch(choose)
		     {
		         case 1:main1(map);break; 
			     case 2:main2(map);break; 
                 case 3:main3(map,D,P);break;
			     case 0:exit(0); 
			     default:cout<<"输入有误,请重新输入:"<<endl;goto leap0;
		     }
	}
	return 0;
}

仅作留档。

你可能感兴趣的:(算法设计与应用)