PAT甲级 1030 Travel Plan

本文详细解析PAT甲级1030TravelPlan题目的算法实现,介绍如何通过Dijkstra算法找到两点间同时具有最小距离和成本的路径,并利用深度优先搜索确定最优路径的成本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PAT甲级 1030 Travel Plan

题目输入

line1 : N (城市个数) M(城市间边数) S(起点城市编号) D(终点城市编号)

line 2 ~ M +1 : City1(城市编号1) City2(城市编号2) Distance(城市间边第一权重)Cost(城市间边第二权重)

要求输出

line1 : 最短路径节点编号序列(从S—>D, 其中路径所含edge的Distance和Cost之和均要最小) 最短路径的Distance和 最短路径的Cost和

代码示例

文件“A 1030 Travel Plan.h”

#include<cstdio>
#include<vector>
#include<algorithm>

using namespace std;

#define MAX 510  //array capacity
#define INF 100000000  //infinity

//given
int num_cities, num_ways, id_start, id_des;  //define variables for input in line1
int weightDist[MAX][MAX], weightCost[MAX][MAX];  //define 2 weighted graph

//assistance
bool IsVisited[MAX] = { false };  //check vertexs which are visited or not
#define NewOptPath(id_pre, id_ct) ( Dis_optPath[id_pre] + weightDist[id_pre][id_ct] < Dis_optPath[id_ct] )  //is there a smaller total distance
#define UpdateOptDist(id_pre, id_ct) ( Dis_optPath[id_ct] = Dis_optPath[id_pre] + weightDist[id_pre][id_ct] )  //update total distance
#define SameOptPath(id_pre, id_ct) ( Dis_optPath[id_pre] + weightDist[id_pre][id_ct] == Dis_optPath[id_ct] )  //is there a equal total distance but different path
//calculate 
int Dis_optPath[MAX], Cos_optPath = INF;  //optDistance of each city (from id_start) & Cost of optPath (from id_start to id_des)
vector<int> pre[MAX];  //closest predecessor of each city
vector<int> tempPath, optPath;  //temporary path & opt path

void Dijkstra() {

	//initial Distance & Cost of optPath
	fill(Dis_optPath, Dis_optPath + MAX, INF);
	Dis_optPath[id_start] = 0;  //默认 id_start--->id_start 的total distance 为0

	//n个顶点依次作为id_pre
	for (int i = 0; i < num_cities; i++) {
		int id_pre = -1, MIN = INF;  //initialize, easy to find isolated city

		for(int id_ct = 0; id_ct < num_cities; id_ct++)  //find a vertex
			//search for unVisited & min of Dis_optPath
			if (!IsVisited[id_ct] && Dis_optPath[id_ct] < MIN) {
				id_pre = id_ct;
				MIN = Dis_optPath[id_ct];
			}

		if (id_pre == -1) return;  //cannot find 
		//find
		IsVisited[id_pre] = true;  //mark
		for (int id_ct = 0; id_ct < num_cities; id_ct++) {  //遍历n个顶点,check 以id_pre为pred时是否要优化
			if (!IsVisited[id_ct] && weightDist[id_pre][id_ct] < INF) { //unvisited & reachable vertex
				if (NewOptPath(id_pre, id_ct)) {
					UpdateOptDist(id_pre, id_ct);
					pre[id_ct].clear();  //clear predecessor of id_ct
					pre[id_ct].push_back(id_pre);  //update closest predecesspr
				}
				else if( SameOptPath(id_pre, id_ct) )
					pre[id_ct].push_back(id_pre);  //update predecesspr directly
			}
		}
 	}
}

void DFS( int id_ct ) {
	//iteration base
	if (id_ct == id_start) {
		tempPath.push_back(id_ct);  //add id_ct in tempPath
		//calculate tempCost of tempPath
		int tempCost = 0;  //initialize
		for (int i = tempPath.size() - 1; i > 0; i--) {  //add cost from back to forth
			int idV = tempPath[i], idVNext = tempPath[i - 1];  
			tempCost += weightCost[idVNext][idV];  
		} 

		 //is there a smaller optCost
		if (tempCost < Cos_optPath) {
			Cos_optPath = tempCost;  //update Cos_optPath
			optPath = tempPath;  //update optPath
		}
		tempPath.pop_back();  //tempPath的首节点出栈
		return;
	}

	tempPath.push_back(id_ct);  //入栈
	for( unsigned i = 0; i < pre[id_ct].size(); i++)  //每个前驱遍历其所有optPath
		DFS( pre[id_ct][i] );  //顺序选一条optPath深入,直到遇到leaf

	tempPath.pop_back();  //每check完一个tempPath上一个节点, 节点出栈
}

文件“main.cpp”

int main() {

//input line1 
	scanf("%d %d %d %d", &num_cities, &num_ways, &id_start, &id_des);

//input line2~M+1 matrix
	//initialize
	fill(weightDist[0], weightDist[0]+ MAX * MAX, INF);  //weightDist[][] = INF
	fill(weightCost[0], weightCost[0] + MAX * MAX, INF);  //weightCost[][] = INF
	for (int i = 0; i < num_cities; i++)  //self-reachable
		weightDist[i][i] = 0, weightCost[i][i] = 0;
	//input
	int id_ct1 = 0, id_ct2 = 0;
	for (int i = 0; i < num_ways; i++) {
		scanf("%d %d", &id_ct1, &id_ct2);
		scanf("%d", &weightDist[id_ct1][id_ct2]);
		scanf("%d", &weightCost[id_ct1][id_ct2]);
		
		weightDist[id_ct2][id_ct1] = weightDist[id_ct1][id_ct2];  //directed weightDist graph
		weightCost[id_ct2][id_ct1] = weightCost[id_ct1][id_ct2];  //directed weightCost graph
	}

	//调用算法
	Dijkstra();  //1.记录最短路径每层的最优前驱集合(有多少条Dist_optPath可以到达该层)
	DFS( id_des );  //calculate Cost_optPath based on Dist_optPath

//output
	//line1: cities from id_start--->id_des
	for (int i = optPath.size() - 1; i >= 0; i--)  //从栈顶开始输出
		//optPath.size() == 0 ???d
		printf("%d ", optPath[i]);  //不要加“&”!!!
	//line2: distance & cost
	printf("%d %d\n", Dis_optPath[id_des], Cos_optPath);  //不要加“&”

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值