PAT 1030 Travel Plan (30 分)迪杰斯特拉算法 燚

A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤500) is the number of cities (and hence the cities are numbered from 0 to N−1); Mis the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

City1 City2 Distance Cost

where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

Sample Output:

0 2 3 3 40

大意: 给出一张地图,上面有各个城市以及每个城市间的距离 以及从城市A到城市B所需花费。求从出发点到目的地的最短路径,如果最短路径有多条则选出花费最小的那条路径。

输入数据:第一行,给定一定数量的城市N个编号为0~N-1,再给出N个城市间有M条路,以及旅游的出发点S和目的地D。

                 后面M行:给出两个城市A,B  以及城市间的距离Len  从A到B 或者 从B到A 所需花费

输出数据:输出从出发点S到目的地D 所经过的城市编号   以及S到D的最短路径距离   总的花费

解题思想:该题为单源最短路径问题,因此选择迪杰斯特拉算法。唯一难度就是在最短路径有多条的情况下选择花费最短的一条(普通迪杰斯特拉算法为随机选择一条)。

关于图的存储:1.邻接链表,2.邻接矩阵 ,3用vector创建一个类似邻接链表的长短不一的二维数组(比邻接矩阵更节约空间,又能随机访问,)结合了前两种存储方式的优点

知识点:最优子结构思想     迪杰斯特拉算法

此题为单源最短路径算法的应用  没有坑。


#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
struct Node {
	int distance = 1000;  //到出发点的距离
	int parent = -1;  //存储该节点的前驱(是从哪个城市到达该节点)
	bool visit = false; //是否已走过这个城市
	int cast = 0;  //从出发点到该城市的花费
};
//DC 为图的节点A
struct DC {
	int node; // 存储与该城市A相连的城市B的编号
	int len;  //两城市间的距离
	int cast;  //两城市间的花费
};
vector<DC>G[500]; //创建二维数组的头
//输入
void input(int n) {
	for (int i = 0; i < n; i++) {
		int node1, node2; //城市A,B的编号
		DC temp;
		cin >> node1 >> node2 >> temp.len >> temp.cast;
		temp.node = node2;
		G[node1].push_back(temp); //在G[A]的vector中加入B
		temp.node = node1;
		G[node2].push_back(temp);//在G[B]的vector中加入A
	}
}
//计算最短路径
void compute(vector<Node> &nodes, int s, int d) {
	//将出发点设为访问  自身到自身的距离为0
	nodes[s].visit = true;
	nodes[s].distance = 0;
	//不断循环  直到到达目的地为止
	while (!nodes[d].visit) {
		//访问与s城市相连接的其他城市
		for (int i = 0; i < G[s].size(); i++) { 
			 //如果该城市没有被访问过 则比较他之前的距离信息与从s点到该城市的距离,决定是否更新该城市信息
			if (!nodes[G[s][i].node].visit) {  
				if (nodes[G[s][i].node].distance > G[s][i].len + nodes[s].distance) {
					nodes[G[s][i].node].distance = G[s][i].len + nodes[s].distance;//出发点到s点的距离加上s点到该点的距离
					nodes[G[s][i].node].parent = s;
					nodes[G[s][i].node].cast = G[s][i].cast + nodes[s].cast;//出发点的花费加上s点到该点的花费
				}
				//如果该城市的距离信息与从s点到达该城市的距离相等  则比较花费 来决定是否更新信息
				else if (nodes[G[s][i].node].distance == G[s][i].len + nodes[s].distance&&nodes[G[s][i].node].cast > G[s][i].cast + nodes[s].cast) {
					nodes[G[s][i].node].distance = G[s][i].len + nodes[s].distance;
					nodes[G[s][i].node].parent = s;
					nodes[G[s][i].node].cast = G[s][i].cast + nodes[s].cast;
				}
			}
		}
		int min;
		//找到一个还没被访问的节点其编号赋值给min
		for (int i = 0; i < nodes.size(); i++) {
			if (!nodes[i].visit) {
				min = i;
				break;
			}
		}
		//找到所有没有被访问的点中距出发点最短的那个点
		for (int i = 0; i < nodes.size(); i++) {
			if ((!nodes[i].visit) && nodes[i].distance < nodes[min].distance) {
				min = i;
			}
		}
		s = min;//将距离最小的点的编号赋值给s
		nodes[min].visit = true;//将该节点设置为已访问过
	}
}
int main() {
	int n, m, s, d;
	cin >> n >> m >> s >> d;
	input(m);
	vector<Node> nodes(n);
	compute(nodes, s, d);
	//因为每个节点中存储有他的前驱(从那个点到达该点的)所以可以从目的点反向寻找,因此用栈存储
	stack<int> st; 
	while (d != s) {
		st.push(d);
		d = nodes[d].parent;
	}
	int allLen = 0, allCast = 0;
	cout << s << " ";
	while (st.size()>1) {
		cout << st.top() << " ";
		st.pop();
	}
	cout << st.top() << " " << nodes[st.top()].distance << " " << nodes[st.top()].cast << endl;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值