PAT A-1131 Subway Map

本文介绍了一种使用深度优先搜索(DFS)解决地铁地图中从起点到终点的最短路径问题的方法,避免了Floyd算法在系数图中的复杂性,通过邻接矩阵存储并进行剪枝。作者分享了代码片段以及解决方案的详细过程。
摘要由CSDN通过智能技术生成

本题未通过所有测试案例(22/30),希望有大佬能解答

本题链接:1131 Subway Map - PAT (Advanced Level) Practice (pintia.cn)

题意:

  给一个地铁地图,求从一地到另一地如何乘车所经站最少,如有多条路线则找转乘次数少的那条路。

思路:

  其实对于图论最优路径问题,不一定非要用Djikstra或者floyd算法,可以单纯的用一个dfs处理。

  本题是多源求最短路径问题,本来想着是用floyd,但是本题为系数图·用矩阵存储特别不方便,因此采用邻接矩阵存储,用直接用dfs列举所有情况进行剪枝,重要的是注意需要回溯

代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int n;
const int N = 10010;
const int INF = 10000000000;
vector<vector<int>> mp;
int line[N][N];//用于记录该点在几号线上


int start, destination;
vector<int> temp, path;
int minStation = INF, minChange = INF;//用于存储最优情况
int nowStation = 0, nowChange = 0;//用于存储当前
bool vis[N];

void init() {
	vector<int> a;
	for (int i = 0; i < N; i++) {
		mp.push_back(a);
	}
	fill(vis, vis + N, false);
}
void dfs(int now) {
	//如果当前跑的太多还没到终点,直接return
	if (nowStation > minStation) {
		return;
	}
	if (now == destination) {
		temp.push_back(now);
		int nowSt = line[temp[0]][temp[1]];
		nowChange = 1;
		for (int i = 1; i < temp.size(); i++) {
			if (line[temp[i - 1]][temp[i]] != nowSt) {
				nowChange++;
				nowSt = line[temp[i - 1]][temp[i]];
			}
		}
		if (nowStation < minStation) {
			
			minChange = nowChange;
			minStation = nowStation;
			if (path.size() > 0) path.clear();
			for (int i = 0; i < temp.size(); i++) {
				path.push_back(temp[i]);
			}
			
		}
		else if (nowStation == minStation) {
			if (nowChange < minChange) {
				minChange = nowChange;
				minStation = nowStation;
				if (path.size() > 0) path.clear();
				for (int i = 0; i < temp.size(); i++) {
					path.push_back(temp[i]);
				}
			}
		}
		temp.pop_back();
		return;
	}

	vis[now] = true;
	nowStation++;
	temp.push_back(now);
	for (int i = 0; i < mp[now].size(); i++) {
		if (!vis[mp[now][i]]) {
			dfs(mp[now][i]);
		}
	}
	nowStation--;
	vis[now] = false;
	temp.pop_back();
}


int main() {
	init();

	cin >> n;
	
	for (int i = 1; i <= n; i++) {
		int m;
		cin >> m;
		int now;
		cin >> now;
		for (int j = 0; j < m - 1; j++) {
			int next;
			cin >> next;
			mp[now].push_back(next);
			mp[next].push_back(now);
			line[now][next] = i;
			line[next][now] = i;
			now = next;
		}

	}
	int k;
	cin >> k;

	for (int i = 0; i < k; i++) {
		path.clear();
		temp.clear();
		cin >> start >> destination;
		nowStation = 0, nowChange = 1;
		minStation = INF, minChange = INF;
		dfs(start);
		cout << minStation << endl;
		if (minChange == 1) {
			printf("Take Line#%d from %04d to %04d.\n",line[path[0]][path[1]], path[0], path[path.size() - 1]);
		}
		else {
				int nLine = line[path[0]][path[1]];
				int beginS = path[0];
				int endS = path[0];
				for (int kk = 1; kk < path.size(); kk++) {
					if (line[path[kk - 1]][path[kk]] != nLine) {
						printf("Take Line#%d from %04d to %04d.\n", nLine, beginS, endS);
						nLine = line[path[kk - 1]][path[kk]];
						beginS = path[kk-1];
					}
					else {
						endS = path[kk];
					}

				}
				printf("Take Line#%d from %04d to %04d.\n", nLine, beginS,path[path.size() - 1]);
		}
		
 	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值