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;
}
欢迎大家批评改正!!!
上一篇: 大数据时代的大展望