欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-08 08:10:26
...

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;
}

PTA:7-101 天梯地图 (30分)---加解析(dfs深度搜索)
欢迎大家批评改正!!!