记PAT A1030题的解题过程

在这里插入图片描述

翻译一下,这里求的是从S这个城市到D这个城市。要求旅行的距离是最短的,这是第一尺度。然后,在旅行的距离最短的前提下,还要求尽可能的使花费最小。输入的格式是 点数,边数,起点城市,终点城市。接下来是每两个城市之间的距离和花费。输出是最短路径,最短的距离和最低的花费。
这是一个典型的最短路径问题,且权值非负,单源最短路径。所以适合Dijkstra算法。总体的框架我们确定了。又由于这个问题有点复杂,第二尺度以及输出的信息比较多。第二尺度以及输出的信息的处理可以单独列一个函数来处理,免得Dijkstra函数内部逻辑太复杂。具体请看代码,AC代码,里面有详细的注释。

#include <iostream>
#include <vector>
using namespace std;

const int MAXV = 1000;
const int INF = 1000000000;

int g[MAXV][MAXV];  //记录边的距离。
int g1[MAXV][MAXV];  //记录边的花费。
bool vit[MAXV] = { false };  //记录这个节点是否被访问。
int d[MAXV];  //记录最短距离。
vector<int> pre[MAXV];  //记录前驱的数组,里面记录的是所有最短路径的前驱。
vector<int> path, temppath;
int optvalue = INF;

//本题打算采用Dijkstra+DFS
void Dijkstra(int n) {
	for (int i = 0; i < n; i++) {
		int u = -1; int MIN = INF;
		for (int j = 0; j < n; j++) {
			if (vit[j] == false && d[j] < MIN) {
				MIN = d[j];
				u = j;
			}
		}
		//这个for循环就是找到目前的还未被访问的点中,距离最小的。
		if (u == -1) { return; }  //如果不连通,就直接返回。
		vit[u] = true;
		for (int v = 0; v < n; v++) {
			if (vit[v] == false && g[u][v] > 0 && d[u] + g[u][v] < d[v]) {
				d[v] = d[u] + g[u][v];
				pre[v].clear();
				pre[v].push_back(u);  
				//如果从u到v可以使距离更短,那么就使v得前驱是u,并且清空v 的其他前驱。
			}
			else if (vit[v] == false && g[u][v] > 0 && d[u] + g[u][v] == d[v]) {
				pre[v].push_back(u);
				//如果一样大,那么就使u也称为v的前驱之一。
			}
		}
		//这个for循环就是把从u到v,可以使距离变得更小的点拿出来。优化最短距离和保存好最优路径。
	}
}
//这个函数运行完之后,d[C2]就是最短距离了,但还需要求出最小的花费以及此时的路径。
//并且pre这个二维的数组也存储了相应的前驱信息。

void DFS1(int C1,int C2) {
	if (C2 == C1) {
		temppath.push_back(C2);
		int value = 0;
		for (int i = 0; i < temppath.size() - 1; i++) {
			value = value + g1[temppath[i]][temppath[i+1]];
		}
		if (value < optvalue) {
			optvalue = value;
			path = temppath;
		}
		temppath.pop_back();
		return;
	}
	//先处理边界。或者说是递归出口。
	temppath.push_back(C2);
	for (int i = 0; i < pre[C2].size(); i++) {
		DFS1(C1, pre[C2][i]);
	}
	//对每一个点来再DFS1.
	temppath.pop_back();   //这个点的前驱已经都处理了,弹出,处理下一个点了。
}

int main() {
	int N, M, C1, C2;
	cin >> N >> M >> C1 >> C2;
	fill(d, d + MAXV, INF);
	d[C1] = 0;
	for (int i = 0; i < M; i++) {
		int a1, b1, c1, d1;
		cin >> a1 >> b1 >> c1 >> d1;
		g[a1][b1] = g[b1][a1] = c1;
		g1[a1][b1] = g1[b1][a1] = d1;
	}
	Dijkstra(N);
	DFS1(C1,C2);
	for (int j = path.size()-1; j >= 0; j--) {
		cout << path[j] << " ";
	}
	cout << d[C2] << " " << optvalue;
	return 0;
}

好了,这道题目就写到这里。谢谢阅读!

原创文章 77 获赞 4 访问量 9048

猜你喜欢

转载自blog.csdn.net/weixin_40007143/article/details/104702147