【无标题】两天不想放弃

#include<iostream>
#include<fstream>
#include<queue>
#include<stack>
using namespace std;
#pragma warning(disable:4996) 
#define MAXSTATION 5200
typedef struct Station
{
	int Num = -1;//从0开始编号
	char Name[52];
	int bus_count = 0;//经过该站的bus数
	int bus_num[100];//经过该站bus的编号;是有序的
}Station;
typedef struct Bus
{
	int Num = 0;//某路公交车
	int station_count = 0;//此bus经过的站总数
	int station_num[100];//无序,站的编号
};
int Find_Station_Num(char station_name[]);
int Station_Find_Bus(int start, int end, int two_station_bus[]);//station[start]->station[end]
bool Find_Min_Transfer(char station_start[], char station_end[]);
bool Find_Min_Station(char station_start[], char station_end[]);
void Init(fstream &fp);
void Show_Route(int path[], int n);
void Show_boundary()
{
	cout << "***************************************************************************************************" << endl;
	return;
}
void transfor_path_to_detail(int path[], int n, int detailpath[], int &len);
int Find_Bus_From_Num(int n);//找Num为n的bus,找到返回其在数组中的编号,否则返回-1;
Station station[MAXSTATION];
Bus bus[1000];
int father[MAXSTATION] = { 0 };
int a[MAXSTATION][MAXSTATION] = { 0 };//非零代表ij之间有非零辆车
int b[MAXSTATION][MAXSTATION] = { 0 };//两个站点之间是否直接相邻,非零代表相邻借助bus的种类数
int station_sum_num = 0;
int main()
{
	fstream fp;
	fp.open("4.txt", ios::in);
	if (fp.fail())
	{
		cout << "fail to open the file";
		system("PAUSE");
		exit(0);
	}

	Init(fp);
	char s_start[52];
	char s_end[52];
	cout << "请输入始点:";
	cin >> s_start;
	cout << endl << "请输入终点:";
	cin >> s_end;
	/*bool tell = Find_Min_Transfer(s_start, s_end);
	if (tell == false)
		cout << "不可达" << endl;
	*/
	Find_Min_Station(s_start, s_end);

	system("PAUSE");
}
int Find_Station_Num(char station_name[])//TODO:后期用个hash表来找 //  站名找其编号(也是数组下标)
{
	int index = -1;
	for (int i = 0; station[i].Num != -1; i++)
	{
		if (strcmp(station_name, station[i].Name) == 0)
		{
			index = i;
			break;
		}
	}
	return index;
}
int Station_Find_Bus(int start, int end,int two_station_bus[])//station[start]->station[end],之间的直达bus的编号 ,bus的数量再邻接矩阵中可得到
{																//start,end  为站点的编号  
	int n = a[start][end];
	int k = 0;
	for (int i = 0; i < station[start].bus_count; i++)
	{
		for (int j = 0; j < station[end].bus_count; j++)
		{
			if (station[start].bus_num[i] == station[end].bus_num[j])
			{
				two_station_bus[k++] = station[start].bus_num[i];
				if (k == n)	return n;
			}
			if (station[start].bus_num[i] < station[end].bus_num[j])
				break;
		}
	}
}
bool Find_Min_Transfer(char station_start[], char station_end[])//BFS,找到end就break,
{

	int start = Find_Station_Num(station_start);
	int end = Find_Station_Num(station_end);
	if (start == -1 || end == -1)
	{
		cout << "站点输入错误" << endl;
		return false;
	}
	//BFS
	
	if (a[start][end] != 0)// 直达
	{
		int path[2];
		path[0] = start;
		path[1] = end;
		cout << "最少换乘次数路线如下:" << endl;
		Show_boundary();
		Show_Route(path, 2);
		Show_boundary();
		cout << "无需换乘,直达" << endl;
		return true;
	}
	else
	{
		bool visit[5200];			//init
		memset(visit, false, 5200);
		memset(father, 0, 5200);

		bool success = false;
		queue<int>q;
		q.push(start);
		visit[start] = true;
		father[start] = -1;
		while (!q.empty())
		{
			queue<int>te;
			while (!q.empty())		//同等次数换乘的站
			{
				te.push(q.front());
				q.pop();
			}
			while (!te.empty())
			{
				int k = te.front();
				te.pop();
				for (int i = 0; i < station_sum_num; i++)
				{
					if (visit[i] == false && a[k][i] != 0)
					{
						visit[i] = true;
						father[i] = k;//后面好找路线
						q.push(i);
					}
				}
			}
			for (int i = 0; i < q.size(); i++)//判断是否与end终点连通
			{
				if (a[q.front()][end] != 0)
				{
					
					success = true;
				}
				int k = q.front();
				q.pop();
				q.push(k);
			}
			if (success)
				break;
		}

		if (success == false)
		{
			cout << "没有线路连通两站" << endl;
			return false;
		}
		cout << "最少换乘次数路线如下:" << endl;
		Show_boundary();
		int time = 0;			//换乘次数
		for (int i = 0; i < q.size(); i++)
		{
			int k = q.front();
			q.pop();
			if (a[k][end] != 0)//可达终点,q队列中放在可能可达终点的前一站
			{
				int len = 0;
				int path[100];
				stack<int>temp;
				for (int j = k; father[j] != -1; j = father[j])
				{
					temp.push(j);
				}
				temp.push(start);
				len = temp.size();
				for (int j = 0; j < len; j++)
				{
					path[j] = temp.top();
					temp.pop();
				}
				path[len++] = end;		//path中存起始点站,以及到达他们的中转站
				Show_Route(path, len);
				time = len - 2;
			}
		}
		Show_boundary();
		cout << "换乘次数:" << time << "次" << endl;
	}
	return true;
}
bool Find_Min_Station(char station_start[], char station_end[])
{
	int PATH[5000];
	int min_len = 1000;
	int detailed_path[5000];
//	int **detailed_path = (int**)malloc(100*sizeof(int*));
	int detailed_path_len = 0;

	int start = Find_Station_Num(station_start);
	int end = Find_Station_Num(station_end);
	if (start == -1 || end == -1)
	{  
		cout << "站点输入错误" << endl;
		return false;
	}
	//BFS

	if (a[start][end] != 0)// 直达
	{
		int path[2];
		path[0] = start;
		path[1] = end;
//		detailed_path[path_number] = (int*)malloc(100 * sizeof(int));
		transfor_path_to_detail(path, 2, detailed_path, detailed_path_len);
		if (detailed_path_len < min_len)
		{
			min_len = detailed_path_len;
			for (int i = 0; i < min_len; i++)
			{
				PATH[i] = detailed_path[i];
			}
		}
	}
	else
	{
		bool visit[5200];			//init
		for (int x = 0; x < 5200; x++)
			visit[x] = false;
		memset(father, 0, 5200*sizeof(int));

		queue<int>q;
		q.push(start);
		visit[start] = true;
		father[start] = -1;
		while (!q.empty())
		{
			int k = q.front();
			q.pop();
			for (int i = 0; i < station_sum_num; i++)
			{
				if (visit[i] == false && a[k][i] != 0)
				{
					visit[i] = true;
					father[i] = k;//后面好找路线
					q.push(i);
					if (a[i][end] != 0)
					{
						stack<int>temp;
						temp.push(end);
						for (int j = i; father[j] != -1; j = father[j])
						{
							temp.push(j);
						}
						temp.push(start);
						int n = temp.size();
						int path[500];
						for (int j = 0; j < n; j++)
						{
							path[j] = temp.top();
							temp.pop();
						}
	//					detailed_path[path_number] = (int*)malloc(100 * sizeof(int));
						transfor_path_to_detail(path, n, detailed_path, detailed_path_len);
						if (detailed_path_len < min_len)
						{
							min_len = detailed_path_len;
							for (int i = 0; i < min_len; i++)
							{
								PATH[i] = detailed_path[i];
							}
						}
					}

				}

			}
		}
	}
	//Print
	cout << "经过最少站点数为:" << min_len << "个\n结果如下:\n";
	
	for (int j = 0; j < min_len - 1; j++)
	{
		cout << station[PATH[j]].Name << "->";
	}
	cout << station[PATH[min_len - 1]].Name << endl;
	return true;
}
void Init(fstream &fp)
{
	int buscount = 0;
	while (!fp.eof())
	{
		char num[8];//几路bus
		fp >> num;
		if (fp.fail())	break;
		
		for (int i = 0; i < 8; i++)
		{
			if (num[i] >= '0' && num[i] <= '9')
				bus[buscount].Num = bus[buscount].Num * 10 + num[i] - '0';
			else
				break;
		}
		fp.ignore();// 空格
		fp.ignore();
		fp.ignore();
		char str[1000];
		fp.getline(str, 1000);
		int len = strlen(str);
		int k = 0;
		char s[50];//每个站
		for (int i = 0; i <= len; i++)
		{
			if (str[i] != ',' && str[i] != '\0')
			{
				s[k++] = str[i];
			}
			else//一个站点全部读入完
			{
				s[k] = '\0';
				k = 0;
				int nu = Find_Station_Num(s);
				if (nu == -1)//新站
				{
					//维护station
					station[station_sum_num].Num = station_sum_num;
					strcpy(station[station_sum_num].Name, s);
					station[station_sum_num].bus_num[station[station_sum_num].bus_count] = bus[buscount].Num;
					station[station_sum_num].bus_count++;
					station_sum_num++;
					//维护bus
					bus[buscount].station_num[bus[buscount].station_count] = station_sum_num - 1;
					bus[buscount].station_count++;
				}
				else
				{
					//维护station
					station[nu].bus_num[station[nu].bus_count] = bus[buscount].Num;
					station[nu].bus_count++;
					//只维护bus
					bus[buscount].station_num[bus[buscount].station_count] = nu;
					bus[buscount].station_count++;
				}
			}
		}
	
		buscount++;
	}
	//memset
	for(int i = 0; i < station_sum_num; i++)
		for (int j = 0; j < station_sum_num; j++)
			{
				a[i][j] = 0;
				b[i][j] = 0;
			}

	//update a[][]
	for (int k = 0; k < buscount; k++)
	{
		for (int i = 0; i < bus[k].station_count; i++)
		{
			for (int j = 0; j < bus[k].station_count; j++)
			{
				a[bus[k].station_num[i]][bus[k].station_num[j]]++;
			}
		}
	}
	for (int i = 0; i < station_sum_num; i++)
		a[i][i] = 0;
	//update b[][]
	for (int k = 0; k < buscount; k++)
	{
		for (int i = 1; i < bus[k].station_count; i++)
		{
			b[bus[k].station_num[i-1]][bus[k].station_num[i]]++;
		}
	}
	
	return;
}
void Show_Route(int path[], int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		cout << station[path[i]].Name << " 乘坐 ";
		int tsb[100];
		memset(tsb, 0, 100);
		Station_Find_Bus(path[i], path[i + 1], tsb);
		for (int j = 0; tsb[j]!=0; j++)
		{
			cout << tsb[j] << " ";
		}
		if (tsb[1] != 0)
			cout << "(其中任一)";
		cout << "路公交车到  ";
	}
	cout << station[path[n - 1]].Name << endl;
	return;
}
void transfor_path_to_detail(int path[], int n, int detailpath[], int &len)
{
	len = 0;
	for (int k = 0; k < n - 1; k++)//找path[k]和path[k+1]两个站点之间的最少站
	{	
		int part_len = 0;
		int k_bus_num = 0;//两站之间的公交车数目,可根据a[][]来判断是否将全部公交车遍历完,为了提前结束循环
		for (int i = 0; i < station[path[k]].bus_count; i++)
		{
			for (int j = 0; j < station[path[k + 1]].bus_count; j++)
			{
				if (station[path[k]].bus_num[i] == station[path[k + 1]].bus_num[j])
				{
					k_bus_num++;					
					if (k_bus_num == 1)
					{
						int te_bus = Find_Bus_From_Num(station[path[k]].bus_num[i]);
						int start_index = 0;
						for (int x = 0; x < bus[te_bus].station_count; x++)//定位
						{
							if (bus[te_bus].station_num[x] == path[k])
							{
								start_index = x;
								break;
							}
						}
						for (int x = start_index; x < bus[te_bus].station_count; x++)//正序
						{
							if (bus[te_bus].station_num[x] == path[k + 1])	break;
							detailpath[len++] = bus[te_bus].station_num[x];
							part_len++;
						}
						if (detailpath[len + start_index - bus[te_bus].station_count] == path[k])//逆序
						{
							part_len = 0;
							len = len + start_index - bus[te_bus].station_count;
							for (int x = start_index; x >= 0; x--)
							{
								if (bus[te_bus].station_num[x] == path[k + 1])	break;
								detailpath[len++] = bus[te_bus].station_num[x];
								part_len++;
							}
						}
					}
					else
					{
						bool dir = true;
						int te_len = 0;
						int te_bus = Find_Bus_From_Num(station[path[k]].bus_num[i]);
						int start_index = 0;
						for (int x = 0; x < bus[te_bus].station_count; x++)//定位
						{
							if (bus[te_bus].station_num[x] == path[k])
							{
								start_index = x;
								break;
							}
						}
						for (int x = start_index; x < bus[te_bus].station_count; x++)//正序
						{
							if (bus[te_bus].station_num[x] == path[k + 1])	break;
							te_len++;
						}
						if (bus[te_bus].station_count-start_index == te_len)//逆序
						{
							te_len = 0;
							dir = false;
							for (int x = start_index; x >= 0; x--)
							{
								if (bus[te_bus].station_num[x] == path[k + 1])	break;
								te_len++;
							}
						}
						if (te_len < part_len)
						{
							len = len - part_len;
							if (dir)
							{
								for (int x = start_index; x < bus[te_bus].station_count; x++)
								{
									if (bus[te_bus].station_num[x] == path[k + 1])	break;
									detailpath[len++] = bus[te_bus].station_num[x];
								}
							}
							else
							{
								for (int x = start_index; x >= 0; x--)
								{
									if (bus[te_bus].station_num[x] == path[k + 1])	break;
									detailpath[len++] = bus[te_bus].station_num[x];
								}
							}
							part_len = te_len;
						}

					}


					if (k_bus_num == a[path[k]][path[k + 1]])
					{
						i = station[path[k]].bus_count;
						break;
					}
					break;
				}
			}
		}
	
	}
	detailpath[len++] = path[n - 1];
	return;
}
int Find_Bus_From_Num(int n)
{
	for (int i = 0; i < 1000; i++)
	{
		if (bus[i].Num == n)
			return i;
	}
	return -1;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值