本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。
输入格式
输入在第一行给出两个正整数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
思路
这道题,让人想到一个东西——动态规划。
截止到n个结点的时候走过的最短距离=min(上一次到达自己的最短路径,截止到n-1个结点的时候走过的最短距离+第n-1个结点到第n个结点的距离)
这时要创建这样的一个结构
int times[N+1];
int dis[N+1];
for(int i = 0; i < N; ++i) {
dis[i] = times[i] = INT_MAX;
}
int parent[N+1];
times
是用来存储时间的,dis
是用来存储距离的,parent
是用来存储父节点的。
我们要创建一个队列,这个队列是用来存储当前的位置,当前的距离,当前的时间的。
struct currentPlace {
int currentI;
int length;
int time;
};
queue<currentPlace> q;
对于得到的最短路径,我们要用一个parent
来存储父节点,然后我们要用一个while
循环来得到最短路径。
void findLength(int be, int en, int N) {
int dis[N+1];
for(int i = 0; i < N; ++i) {
dis[i] = INT_MAX;
}
int parent[N+1];
queue<pair<int, int>> q;
q.push({be, 0});
parent[be] = -1;
dis[be] = 0;
while(!q.empty()) {
pair<int, int> top = q.front();
for(int i = 0; i < N; ++i) {
if(map1[top.first][i].canGo && i != parent[top.first]) {
if(dis[i] > top.second+map1[top.first][i].length) {
dis[i] = top.second+map1[top.first][i].length;
parent[i] = top.first;
q.push({i, top.second+map1[top.first][i].length});
}
}
}
q.pop();
}
for(int i = en; i != -1; i = parent[i]) {
lengthdq.insert(lengthdq.begin(), i);
}
lowlength = dis[en];
}
对于得到的最快路径,我们要用一个parent
来存储父节点,然后我们要用一个while
循环来得到最快路径。
这个最快路径的判断条件是,如果时间小于times[i]
,那么就更新times[i]
,如果时间等于times[i]
,那么就判断距离,如果距离小于dis[i]
,那么就更新dis[i]
。
void findTime(int be, int en, int N) {
int times[N+1];
int dis[N+1];
for(int i = 0; i < N; ++i) {
dis[i] = times[i] = INT_MAX;
}
int parent[N+1];
queue<currentPlace> q;
q.push({be, 0, 0});
parent[be] = -1;
times[be] = dis[be] = 0;
while(!q.empty()) {
currentPlace top = q.front();
for(int i = 0; i < N; ++i) {
if(map1[top.currentI][i].canGo && i != parent[top.currentI]) {
if(times[i] > top.time+map1[top.currentI][i].time) {
times[i] = top.time+map1[top.currentI][i].time;
parent[i] = top.currentI;
dis[i] = top.length+map1[top.currentI][i].length;
q.push({i, top.length+map1[top.currentI][i].length, top.time+map1[top.currentI][i].time});
} else if(times[i] == top.time+map1[top.currentI][i].time) {
if(dis[i] > top.length+map1[top.currentI][i].length) {
dis[i] = top.length+map1[top.currentI][i].length;
parent[i] = top.currentI;
times[i] = top.time+map1[top.currentI][i].time;
q.push({i, top.length+map1[top.currentI][i].length, top.time+map1[top.currentI][i].time});
}
}
}
}
q.pop();
}
for(int i = en; i != -1; i = parent[i]) {
timedq.insert(timedq.begin(), i);
}
lowTime = times[en];
}
整个程序的思路
首先,我们要创建一个结构体,这个结构体是用来存储地图的。
struct node {
int length;
int time;
bool canGo;
};
然后,我们要创建一个地图,这个地图是用来存储地图的。
node map1[510][510];
然后,我们要创建一个lengthdq
和timedq
,这个是用来存储最短路径和最快路径的。
vector<int> lengthdq, timedq;
然后,我们要创建一个lowTime
和lowlength
,这个是用来存储最短路径和最快路径的时间和距离。
int lowTime, lowlength;
然后,我们要创建一个findLength
和findTime
,这个是用来找到最短路径和最快路径的。
void findLength(int be, int en, int N) {
int dis[N+1];
for(int i = 0; i < N; ++i) {
dis[i] = INT_MAX;
}
int parent[N+1];
queue<pair<int, int>> q;
q.push({be, 0});
parent[be] = -1;
dis[be] = 0;
while(!q.empty()) {
pair<int, int> top = q.front();
for(int i = 0; i < N; ++i) {
if(map1[top.first][i].canGo && i != parent[top.first]) {
if(dis[i] > top.second+map1[top.first][i].length) {
dis[i] = top.second+map1[top.first][i].length;
parent[i] = top.first;
q.push({i, top.second+map1[top.first][i].length});
}
}
}
q.pop();
}
for(int i = en; i != -1; i = parent[i]) {
lengthdq.insert(lengthdq.begin(), i);
}
lowlength = dis[en];
}
void findTime(int be, int en, int N) {
int times[N+1];
int dis[N+1];
for(int i = 0; i < N; ++i) {
dis[i] = times[i] = INT_MAX;
}
int parent[N+1];
queue<currentPlace> q;
q.push({be, 0, 0});
parent[be] = -1;
times[be] = dis[be] = 0;
while(!q.empty()) {
currentPlace top = q.front();
for(int i = 0; i < N; ++i) {
if(map1[top.currentI][i].canGo && i != parent[top.currentI]) {
if(times[i] > top.time+map1[top.currentI][i].time) {
times[i] = top.time+map1[top.currentI][i].time;
parent[i] = top.currentI;
dis[i] = top.length+map1[top.currentI][i].length;
q.push({i, top.length+map1[top.currentI][i].length, top.time+map1[top.currentI][i].time});
} else if(times[i] == top.time+map1[top.currentI][i].time) {
if(dis[i] > top.length+map1[top.currentI][i].length) {
dis[i] = top.length+map1[top.currentI][i].length;
parent[i] = top.currentI;
times[i] = top.time+map1[top.currentI][i].time;
q.push({i, top.length+map1[top.currentI][i].length, top.time+map1[top.currentI][i].time});
}
}
}
}
q.pop();
}
for(int i = en; i != -1; i = parent[i]) {
timedq.insert(timedq.begin(), i);
}
lowTime = times[en];
}
然后,我们要输入地图的信息。
int N, M, A, B, length, time, oneWay, be, en;
cin >> N >> M;
for(int i = 1; i <= M; ++i) {
cin >> A >> B >> oneWay >> length >> time;
if(oneWay == 0) {
map1[B][A].length = map1[A][B].length = length;
map1[B][A].time = map1[A][B].time = time;
map1[B][A].canGo = map1[A][B].canGo = true;
} else {
map1[A][B].length = length;
map1[A][B].time = time;
map1[A][B].canGo = true;
}
}
cin >> be >> en;
findLength(be, en, N);
findTime(be, en, N);
然后,判断两个路径是否相同,如果相同,就输出Time = T; Distance = D: 起点 => 节点1 => ... => 终点
,否则,就输出Time = T: 起点 => 节点1 => ... => 终点
和Distance = D: 起点 => 节点1 => ... => 终点
。
int flag = 0;
for(int i = 0; i < timedq.size() && i < lengthdq.size(); ++i) {
if(timedq[i] != lengthdq[i]) {
flag = 1;
}
}
if(flag == 0) {
cout << "Time = " << lowTime << "; ";
cout << "Distance = " << lowlength << ": ";
int f = 0;
for(auto i: lengthdq) {
if(f == 0) {
cout << i;
f = 1;
} else
cout << " => " << i;
}
} else {
cout << "Time = " << lowTime << ": ";
int f = 0;
for(auto i: timedq) {
if(f == 0) {
cout << i;
f = 1;
} else
cout << " => " << i;
}
cout << endl;
cout << "Distance = " << lowlength << ": ";
f = 0;
for(auto i: lengthdq) {
if(f == 0) {
cout << i;
f = 1;
} else
cout << " => " << i;
}
}
当然,在这种情况下,我们不使用isGone
来判断是否走过,而是判断i != parent[top.first]
来判断是否走过。
if(map1[top.first][i].canGo && i != parent[top.first])
Code
#include <bits/stdc++.h>
using namespace std;
struct node {
int length;
int time;
bool canGo;
};
struct currentPlace {
int currentI;
int length;
int time;
};
vector<int> lengthdq, timedq;
int lowTime, lowlength;
node map1[510][510];
void findLength(int be, int en, int N) {
int dis[N+1];
for(int i = 0; i < N; ++i) {
dis[i] = INT_MAX;
}
int parent[N+1];
queue<pair<int, int>> q;
q.push({be, 0});
parent[be] = -1;
dis[be] = 0;
while(!q.empty()) {
pair<int, int> top = q.front();
for(int i = 0; i < N; ++i) {
if(map1[top.first][i].canGo && i != parent[top.first]) {
if(dis[i] > top.second+map1[top.first][i].length) {
dis[i] = top.second+map1[top.first][i].length;
parent[i] = top.first;
q.push({i, top.second+map1[top.first][i].length});
}
}
}
q.pop();
}
for(int i = en; i != -1; i = parent[i]) {
lengthdq.insert(lengthdq.begin(), i);
}
lowlength = dis[en];
}
void findTime(int be, int en, int N) {
int times[N+1];
int dis[N+1];
for(int i = 0; i < N; ++i) {
dis[i] = times[i] = INT_MAX;
}
int parent[N+1];
queue<currentPlace> q;
q.push({be, 0, 0});
parent[be] = -1;
times[be] = dis[be] = 0;
while(!q.empty()) {
currentPlace top = q.front();
for(int i = 0; i < N; ++i) {
if(map1[top.currentI][i].canGo && i != parent[top.currentI]) {
if(times[i] > top.time+map1[top.currentI][i].time) {
times[i] = top.time+map1[top.currentI][i].time;
parent[i] = top.currentI;
dis[i] = top.length+map1[top.currentI][i].length;
q.push({i, top.length+map1[top.currentI][i].length, top.time+map1[top.currentI][i].time});
} else if(times[i] == top.time+map1[top.currentI][i].time) {
if(dis[i] > top.length+map1[top.currentI][i].length) {
dis[i] = top.length+map1[top.currentI][i].length;
parent[i] = top.currentI;
times[i] = top.time+map1[top.currentI][i].time;
q.push({i, top.length+map1[top.currentI][i].length, top.time+map1[top.currentI][i].time});
}
}
}
}
q.pop();
}
for(int i = en; i != -1; i = parent[i]) {
timedq.insert(timedq.begin(), i);
}
lowTime = times[en];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int N, M, A, B, length, time, oneWay, be, en;
cin >> N >> M;
for(int i = 1; i <= M; ++i) {
cin >> A >> B >> oneWay >> length >> time;
if(oneWay == 0) {
map1[B][A].length = map1[A][B].length = length;
map1[B][A].time = map1[A][B].time = time;
map1[B][A].canGo = map1[A][B].canGo = true;
} else {
map1[A][B].length = length;
map1[A][B].time = time;
map1[A][B].canGo = true;
}
}
cin >> be >> en;
findLength(be, en, N);
findTime(be, en, N);
int flag = 0;
for(int i = 0; i < timedq.size() && i < lengthdq.size(); ++i) {
if(timedq[i] != lengthdq[i]) {
flag = 1;
}
}
if(flag == 0) {
cout << "Time = " << lowTime << "; ";
cout << "Distance = " << lowlength << ": ";
int f = 0;
for(auto i: lengthdq) {
if(f == 0) {
cout << i;
f = 1;
} else
cout << " => " << i;
}
} else {
cout << "Time = " << lowTime << ": ";
int f = 0;
for(auto i: timedq) {
if(f == 0) {
cout << i;
f = 1;
} else
cout << " => " << i;
}
cout << endl;
cout << "Distance = " << lowlength << ": ";
f = 0;
for(auto i: lengthdq) {
if(f == 0) {
cout << i;
f = 1;
} else
cout << " => " << i;
}
}
}
标签:currentI,int,top,地图,PTA,length,map1,天梯,time
From: https://blog.csdn.net/qq_21739599/article/details/143647475