PTA:7-101 天梯地图 (30分)---加解析(dfs深度搜索)

7-101 天梯地图 (30分)

本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。

输入格式:
输入在第一行给出两个正整数N(2 ≤ N ≤ 500)和M,分别为地图中所有标记地点的个数和连接地点的道路条数。随后M行,每行按如下格式给出一条道路的信息:
V1 V2 one-way length time
其中V1和V2是道路的两个端点的编号(从0到N-1);如果该道路是从V1到V2的单行线,则one-way为1,否则为0;length是道路的长度;time是通过该路所需要的时间。最后给出一对起点和终点的编号。

输出格式:
首先按下列格式输出最快到达的时间T和用节点编号表示的路线:

Time = T: 起点 => 节点1 => … => 终点

然后在下一行按下列格式输出最短距离D和用节点编号表示的路线:

Distance = D: 起点 => 节点1 => … => 终点

如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。

如果这两条路线是完全一样的,则按下列格式输出:

Time = T; Distance = D: 起点 => 节点1 => … => 终点

输入样例1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
5 4 0 2 3
5 9 1 1 4
0 6 0 1 1
7 3 1 1 2
8 3 1 1 2
2 5 0 2 2
2 1 1 1 1
1 5 0 1 3
1 4 0 1 1
9 7 1 1 3
3 1 0 2 5
6 3 1 2 1
5 3

输出样例1:
Time = 6: 5 => 4 => 8 => 3
Distance = 3: 5 => 1 => 3

输入样例2:
7 9
0 4 1 1 1
1 6 1 3 1
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 3 1
3 2 1 2 1
4 5 0 2 2
6 5 1 2 1
3 5

输出样例2:
Time = 3; Distance = 4: 3 => 2 => 5

大部分测试点都通过了。最后一个测试点运行超时,想了很久,也不知道怎么改,还请读者指教。
具体思路解析见代码:

#include<bits/stdc++.h>
using namespace std;

/*
栈st_t保存最快路径;
栈st_l保存最短路径;
栈path保存搜索中动态的路径; 
mint表示最快的时间,mintl表示最快路径的长度; 
minl表示最短路径;
*/ 
int r[520][520],te[520][520],vis[520][520]; //r[i][j]表示i和j地点之间的距离,t[][]表示时间,vis用于深搜中判断地点是否访问过 
int n, m, flag2=0, bg, endd, mint=1e5, mintl=1e5, minl=1e5, sumt=0, suml=0;
stack<int> path,st_t,st_l,temp;

void dsf(int v1, int v2, int l, int t){
	if(sumt+te[v1][v2]>mint&&suml+r[v1][v2]>minl) return;  //剪枝,提高速度 
	if(v2==endd){  //到达终点 
		int flag=0;  //flag和flag2用于判断最快最短路径是否相同		
		if(sumt+te[v1][v2]<mint||(sumt+te[v1][v2]==mint&&suml+r[v1][v2]<mintl)){
			flag2=0; 
			flag++;
			mint = sumt+te[v1][v2];
			mintl = suml+r[v1][v2];
			while(!temp.empty()) temp.pop();//清空 
			while(!st_t.empty()) st_t.pop();//清空
			while(!path.empty()){
				temp.push(path.top());
				st_t.push(path.top());
				path.pop();
			}
			while(!temp.empty()){ //保证path不变,方便进行下一次的判断 
				path.push(temp.top());
				temp.pop();
			}
		}
		if(suml+r[v1][v2]<minl||(suml+r[v1][v2]==minl&&path.size()<st_l.size())){
			flag2=0; 
			flag++;
			minl = suml+r[v1][v2];
			while(!temp.empty()) temp.pop();
			while(!st_l.empty()) st_l.pop();
			while(!path.empty()){
				temp.push(path.top());
				st_l.push(path.top());
				path.pop();
			}
			while(!temp.empty()){
				path.push(temp.top());
				temp.pop();
			}		
		}
		if(flag==2) flag2=1;
		return;
	}
	vis[v1][v2]=1;
	path.push(v2);
	sumt += te[v1][v2];
	suml += r[v1][v2];
	for(int i=0; i<n; i++){
		if(!vis[v2][i]&&r[v2][i]>0){
			dsf(v2, i, r[v2][i], te[v2][i]);
		}
	}	
	vis[v1][v2]=0;
	path.pop();
	sumt -= te[v1][v2];
	suml -= r[v1][v2];
	return;
} 
 
int main(){
	int v1, v2, fg, l, t;
	cin >> n >> m;
	for(int i=0; i<m; i++){
		cin >> v1 >> v2 >> fg >> l >> t;
		r[v1][v2]=l;
		te[v1][v2]=t;
		if(!fg){  //不是单行道的话,则r[v2][v1]也赋值 
			r[v2][v1]=l;
			te[v2][v1]=t;	
		}  
	}	
	cin >> bg >> endd;
	for(int i=0; i<n; i++){ //搜索以bg为起点的道路 
		if(r[bg][i]>0){
			dsf(bg, i, r[bg][i], te[bg][i]);
		}
	}
	
	if(flag2) cout << "Time = "<<mint<<"; Distance = "<<minl<<": "<<bg;
	else cout << "Time = " << mint << ": " << bg;
	while(!st_t.empty()){
		cout << " => ";
		cout << st_t.top();
		st_t.pop();
	}
	cout << " => " << endd << endl;
	
	if(!flag2){   //最快最短路径不同 
		cout << "Distance = " << minl << ": " << bg;
		while(!st_l.empty()){
			cout << " => ";
			cout << st_l.top();
			st_l.pop();
		}
		cout << " => " << endd << endl;
	}
	return 0;
}

在这里插入图片描述
欢迎大家批评改正!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值