zoukankan      html  css  js  c++  java
  • PAT天梯赛L3-007 天梯地图

    题目链接:点击打开链接

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

    输入格式:

    输入在第一行给出两个正整数N(2 <= N <=500)和M,分别为地图中所有标记地点的个数和连接地点的道路条数。随后M行,每行按如下格式给出一条道路的信息:

    V1 V2 one-way length time

    其中V1V2是道路的两个端点的编号(从0到N-1);如果该道路是从V1V2的单行线,则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

    思路:最短路,涉及多个标尺,所以用dijkstra + dfs. 没什么注意的地方。

    AC代码:

    #include<iostream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int MAX = 510;
    const int INF = 0x3f3f3f;
    
    struct node{
    	int v;
    	int len;
    	int time;
    	node() {}
    	node(int _v, int _len, int _time) : v(_v), len(_len), time(_time) {}
    };
    
    int n, m, st, ed;
    
    vector<int> min_path;
    int prepre[MAX];
    vector<node> G[MAX];
    vector<int> pre[MAX];
    vector<int> temppath, anspath;
    vector<int> dispre[MAX];
    int g[MAX][MAX];
    int sum = INF, min_d = INF;
    int d[MAX];
    int t[MAX];
    
    void time_dfs(int v) {
    	if(v == st) {
    		min_path.push_back(v);
    		return;
    	}
    	time_dfs(prepre[v]);
    	min_path.push_back(v);
    }
    
    void len_dfs(int v) {
    	if(v == st) {
    		temppath.push_back(v);
    		int tempans;
    		tempans = temppath.size();
    		if(tempans < sum) {
    			anspath = temppath;
    			sum = tempans;
    		}
    		temppath.pop_back();
    		return;
    	}
    	temppath.push_back(v);
    	for(int i = 0; i < dispre[v].size(); i++) {
    		len_dfs(dispre[v][i]);
    	}
    	temppath.pop_back();
    }
    
    void time_dijsktra(int st) {//储存时间相同的路径
    	bool vis[MAX] = {false};
    	fill(t, t + MAX, INF);
    	t[st] = 0;
    	for(int i = 0; i < n; i++) {
    		prepre[i] = i;
    	}
    	for(int i = 0; i < n; i++) {
    		int u = -1, MIN = INF;
    		for(int j = 0; j < n; j++) {
    			if(vis[j] == false && t[j] < MIN) {
    				u = j;
    				MIN = t[j];
    			}
    		}
    
    		if(u == -1) return ;
    		vis[u] = true;
    		for(int j = 0; j < G[u].size(); j++) {
    			int v = G[u][j].v;
    			if(vis[v] == false) {
    				if(t[u] + G[u][j].time < t[v]) {
    					t[v] = t[u] + G[u][j].time;
    					d[v] = d[u] + g[u][v];//因为这行代码 那个点一直过不去
    					prepre[v] = u;
    				} else if(t[u] + G[u][j].time == t[v] && d[v] > d[u] + g[u][v]) {
    					d[v] = d[u] + g[u][v];
    					prepre[v] = u; 
    				}
    			}
    		}
    	}
    }
    
    void len_dijsktra(int st) {
    	bool vis[MAX] = {false};
    	fill(d, d + MAX, INF);
    	d[st] = 0; 
    	for(int i = 0; i < n; i++) {
    		int u = -1, MIN = INF;
    		for(int j = 0; j < n; j++) {
    			if(vis[j] == false && d[j] < MIN) {
    				u = j;
    				MIN = d[j];
    			}
    		}
    
    		if(u == -1) return ;
    		vis[u] = true;
    		for(int j = 0; j < G[u].size(); j++) {
    			int v = G[u][j].v;
    			if(vis[v] == false) {
    				if(d[u] + G[u][j].len < d[v]) {
    					d[v] = d[u] + G[u][j].len;
    					dispre[v].clear();
    					dispre[v].push_back(u);
    				} else if(d[u] + G[u][j].len == d[v]) {
    					dispre[v].push_back(u);
    				}
    			}  
    		}
    	}
    }
    
    int main() {
    	int u, v, flag, dis, hour;
    	cin >> n >> m;
    	while(m--) {
    		scanf("%d%d%d%d%d", &u, &v, &flag, &dis, &hour);
    		if(flag) {
    			G[u].push_back(node(v, dis, hour));
    			g[u][v] = dis;
    		} else {
    			G[u].push_back(node(v, dis, hour));
    			G[v].push_back(node(u, dis, hour)); 
    			g[u][v] = g[v][u] = dis;
    		}
    	}
    	cin >> st >> ed;
    	time_dijsktra(st);
    	time_dfs(ed);
    	reverse(min_path.begin(), min_path.end());//因为两条结果路中的 储存顺序不一样。
    	len_dijsktra(st);
    	len_dfs(ed);
    
    	if(min_path != anspath) {
    		printf("Time = %d: ", t[ed]);
    		for(int i = min_path.size() - 1; i >= 0; i--) {
    			if(i == 0)
    				printf("%d
    ", min_path[i]);
    			else
    				printf("%d => ", min_path[i]);
    		}
    		printf("Distance = %d: ", d[ed]);
    		for(int i = anspath.size() - 1; i >= 0; i--) {
    			if(i == 0)
    				printf("%d", anspath[i]);
    			else
    				printf("%d => ", anspath[i]);
    		}
    	} else {
    		printf("Time = %d; Distance = %d: ", t[ed], d[ed]);
    		for(int i = min_path.size() - 1; i >= 0; i--) {
    			if(i == 0)
    				printf("%d", min_path[i]);
    			else
    				printf("%d => ", min_path[i]);
    		}
    	}
    	return 0;
    }

    当时卡了我两天的代码,问题所在

    AC代码:

    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int MAX = 510;
    const int INF = 0x3f3f3f;
    
    struct node{
    	int v;
    	int len;
    	int time;
    	node() {}
    	node(int _v, int _len, int _time) : v(_v), len(_len), time(_time) {}
    };
    
    int n, m, st, ed;
    
    vector<int> path, min_path;
    vector<node> G[MAX];
    vector<int> pre[MAX];//储存第一标尺相同的路
    vector<int> temppath, anspath;//临时路,结果路。
    vector<int> dispre[MAX];//储存遍历第一标尺相同的路
    int g[MAX][MAX];//距离
    int sum = INF, min_d = INF;
    
    int d[MAX];
    int t[MAX];
    
    void dfs(int v) {//时间相同,最短路
    	if(v == st) {
    		path.push_back(v);
    		int tempd = 0;
    		for(int i = path.size() - 1; i > 0; i--) { // 原来是正序相加的 改为逆序就对了 后来想到是因为题目中(单双向)不确定 坑点!
    			tempd += g[path[i]][path[i-1]];
    		}
    		if(tempd < min_d) {
    			min_path = path;
    			min_d = tempd;
    		}
    		path.pop_back();
    		return;
    	}
    	path.push_back(v);
    	for(int i = 0; i < pre[v].size(); i++) {
    		dfs(pre[v][i]);
    	}
    	path.pop_back();
    }
    
    void len_dfs(int v) {距离相同,路径节点最少的
    	if(v == st) {
    		temppath.push_back(v);
    		int tempans;
    		tempans = temppath.size();
    		if(tempans < sum) {
    			anspath = temppath;
    			sum = tempans;
    		}
    		temppath.pop_back();
    		return;
    	}
    	temppath.push_back(v);
    	for(int i = 0; i < dispre[v].size(); i++) {
    		len_dfs(dispre[v][i]);
    	}
    	temppath.pop_back();
    }
    
    void time_dijsktra(int st) {//储存时间相同的路
    	bool vis[MAX] = {false};
    	fill(t, t + MAX, INF);
    	t[st] = 0;
    	for(int i = 0; i < n; i++) {
    		int u = -1, MIN = INF;
    		for(int j = 0; j < n; j++) {
    			if(vis[j] == false && t[j] < MIN) {
    				u = j;
    				MIN = t[j];
    			}
    		}
    
    		if(u == -1) return ;
    		vis[u] = true;
    		for(int j = 0; j < G[u].size(); j++) {
    			int v = G[u][j].v;
    			if(vis[v] == false) {
    				if(t[u] + G[u][j].time < t[v]) {
    					t[v] = t[u] + G[u][j].time;
    					pre[v].clear();
    					pre[v].push_back(u);
    				} else if(t[u] + G[u][j].time == t[v]) {
    					pre[v].push_back(u);
    				}
    			}
    		}
    	}
    }
    
    void len_dijsktra(int st) {//储存距离相同的路
    	bool vis[MAX] = {false};
    	fill(d, d + MAX, INF);
    	d[st] = 0; 
    	for(int i = 0; i < n; i++) {
    		int u = -1, MIN = INF;
    		for(int j = 0; j < n; j++) {
    			if(vis[j] == false && d[j] < MIN) {
    				u = j;
    				MIN = d[j];
    			}
    		}
    
    		if(u == -1) return ;
    		vis[u] = true;
    		for(int j = 0; j < G[u].size(); j++) {
    			int v = G[u][j].v;
    			if(vis[v] == false) {
    				if(d[u] + G[u][j].len < d[v]) {
    					d[v] = d[u] + G[u][j].len;
    					dispre[v].clear();
    					dispre[v].push_back(u);
    				} else if(d[u] + G[u][j].len == d[v]) {
    					dispre[v].push_back(u);
    				}
    			}  
    		}
    	}
    }
    
    int main() {
    	int u, v, flag, dis, hour;
    	cin >> n >> m;
    	while(m--) {
    		scanf("%d%d%d%d%d", &u, &v, &flag, &dis, &hour);
    		if(flag) {
    			G[u].push_back(node(v, dis, hour));
    			g[u][v] = dis;
    		} else {
    			G[u].push_back(node(v, dis, hour));
    			G[v].push_back(node(u, dis, hour)); 
    			g[u][v] = g[v][u] = dis;
    		}
    	}
    	cin >> st >> ed;
    	time_dijsktra(st);
    	dfs(ed);
    	len_dijsktra(st);
    	len_dfs(ed);
    	//	for(int i = 0; i < path.size(); i++) {
    	//		printf("%d ", path[i]);
    	//	}
    	//	printf("
    ");
    	//	reverse(anspath.begin(), anspath.end());
    	//	for(int i = 0; i < anspath.size(); i++) {
    	//		printf("%d ", anspath[i]);
    	//	}
    	//	printf("
    ");
    	if(min_path != anspath) {
    		printf("Time = %d: ", t[ed]);
    		for(int i = min_path.size() - 1; i >= 0; i--) {
    			if(i == 0)
    				printf("%d
    ", min_path[i]);
    			else
    				printf("%d => ", min_path[i]);
    		}
    		printf("Distance = %d: ", d[ed]);
    		for(int i = anspath.size() - 1; i >= 0; i--) {
    			if(i == 0)
    				printf("%d", anspath[i]);
    			else
    				printf("%d => ", anspath[i]);
    		}
    	} else {
    		printf("Time = %d; Distance = %d: ", t[ed], d[ed]);
    		for(int i = min_path.size() - 1; i >= 0; i--) {
    			if(i == 0)
    				printf("%d", min_path[i]);
    			else
    				printf("%d => ", min_path[i]);
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    771. Jewels and Stones
    706. Design HashMap
    811. Subdomain Visit Count
    733. Flood Fill
    117. Populating Next Right Pointers in Each Node II
    250. Count Univalue Subtrees
    94. Binary Tree Inorder Traversal
    116. Populating Next Right Pointers in Each Node
    285. Inorder Successor in BST
    292. Nim Game Java Solutin
  • 原文地址:https://www.cnblogs.com/ACMerszl/p/9573001.html
Copyright © 2011-2022 走看看