Programming Challenges 习题10.5.4

PC/UVa:111004/10039

Railroads

据说这题可以用动态规划来解,不过书上给的提示是最短路径。可以首先使用Dijkstra求出发城市到目的城市的最早到达时间,然后再将图中的边反向(即火车从到达时间开出,在开出时间到达),再次使用Dijkstra求最短路,查找回到出发城市最短时间,即最晚出发时间。

还有这题的输入不太好理解,每一趟列车是可以停靠多个车站的,而不是只有始发站和终点站。

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <iomanip>

#define MIN_DEPARTURE 0
#define MAX_ARRIVAL 2400

using namespace std;

struct Train
{
	int tDeparture;
	int tArrival;
	size_t ID;
	Train(const int tDeparture, const int tArrival, const size_t ID)
		: tDeparture(tDeparture), tArrival(tArrival), ID(ID){};
};

void input(size_t &C, map<string, size_t> &mCity2ID, vector<string> &vsID2City,
	vector<vector<Train>> &Graph, vector<vector<Train>> &RGraph,
	int &time, string &strDeparture, string &strArrival)
{
	cin >> C;
	cin.get();
	vsID2City.assign(C, "");
	for (size_t c = 0; c < C; c++)
	{
		cin >> vsID2City[c];
		mCity2ID.insert(pair<string, size_t>(vsID2City[c], c));
	}
	Graph.assign(C, vector<Train>());
	RGraph.assign(C, vector<Train>());
	int T = 0;
	cin >> T;
	for (int t = 0; t < T; t++)
	{
		int S = 0, tDeparture, tArrival;
		size_t idDeparture, idArrival;
		cin >> S;
		cin >> tDeparture;
		cin.get();
		cin >> strDeparture;
		idDeparture = mCity2ID[strDeparture];
		for (int s = 1; s < S; s++)
		{
			cin >> tArrival;
			cin.get();
			cin >> strArrival;
			idArrival = mCity2ID[strArrival];
			Graph[idDeparture].push_back(Train(tDeparture, tArrival, idArrival));
			RGraph[idArrival].push_back(Train(tDeparture, tArrival, idDeparture));
			tDeparture = tArrival;
			idDeparture = idArrival;
		}
	}
	cin >> time;
	cin.get();
	cin >> strDeparture >> strArrival;
}

int findMinArrival(const vector<vector<Train>> &Graph,
	const size_t idDeparture, const size_t idArrival, const int earliest)
{
	size_t Cities = Graph.size();
	vector<int> viMinArrival(Cities, MAX_ARRIVAL);
	vector<int> viOpen(Cities, MAX_ARRIVAL);
	size_t idCurr = idDeparture;
	viMinArrival[idDeparture] = earliest;
	while (1){
		const vector<Train> &vecTrain = Graph[idCurr];
		for (auto train : vecTrain)
		{
			if (viMinArrival[train.ID] == MAX_ARRIVAL &&
				train.tDeparture >= viMinArrival[idCurr]){
				if (train.tArrival < viOpen[train.ID]){
					viOpen[train.ID] = train.tArrival;
				}
			}
		}
		int minArrival = MAX_ARRIVAL;
		size_t minArrivalIdx;
		for (size_t i = 0; i < viOpen.size(); i++)
		{
			if (viOpen[i] < minArrival){
				minArrival = viOpen[i];
				minArrivalIdx = i;
			}
		}
		if (minArrival == MAX_ARRIVAL) break;
		viMinArrival[minArrivalIdx] = minArrival;
		viOpen[minArrivalIdx] = MAX_ARRIVAL;//将其还原
		idCurr = minArrivalIdx;
		if (idCurr == idArrival) break;
	}
	return viMinArrival[idArrival];
}

int findMaxDeparture(const vector<vector<Train>> &Graph,
	const size_t idDeparture, const size_t idArrival, const int earliest)
{
	size_t Cities = Graph.size();
	vector<int> viMaxDeparture(Cities, MIN_DEPARTURE);
	vector<int> viOpen(Cities, MIN_DEPARTURE);
	size_t idCurr = idArrival;
	viMaxDeparture[idArrival] = earliest;
	while (1){
		const vector<Train> &vecTrain = Graph[idCurr];
		for (auto train : vecTrain)
		{
			if (viMaxDeparture[train.ID] == MIN_DEPARTURE &&
				train.tArrival <= viMaxDeparture[idCurr]){
				if (train.tDeparture > viOpen[train.ID]){
					viOpen[train.ID] = train.tDeparture;
				}
			}
		}
		int maxDeparture = MIN_DEPARTURE;
		size_t maxDepartureIdx;
		for (size_t i = 0; i < viOpen.size(); i++)
		{
			if (viOpen[i] > maxDeparture){
				maxDeparture = viOpen[i];
				maxDepartureIdx = i;
			}
		}
		if (maxDeparture == MIN_DEPARTURE) break;
		viMaxDeparture[maxDepartureIdx] = maxDeparture;
		viOpen[maxDepartureIdx] = MIN_DEPARTURE;//将其还原
		idCurr = maxDepartureIdx;
		if (idCurr == idDeparture) break;
	}
	return viMaxDeparture[idDeparture];
}

int main()
{
	int T = 0;
	cin >> T;
	for (int t = 0; t < T; t++)
	{
		size_t C;
		map<string, size_t> mCity2ID;
		vector<string> vsID2City;
		vector<vector<Train>> Graph, RGraph;
		int earliest;
		string strDeparture, strArrival;
		input(C, mCity2ID, vsID2City, Graph, RGraph, earliest, strDeparture, strArrival);
		cout << "Scenario " << t + 1 << endl;
		int earliestArrival = findMinArrival(Graph, mCity2ID[strDeparture], mCity2ID[strArrival], earliest);
		if (earliestArrival == MAX_ARRIVAL){
			cout << "No connection" << endl;
		}
		else{
			int latestDeparture = findMaxDeparture(RGraph, mCity2ID[strDeparture], mCity2ID[strArrival], earliestArrival);
			cout << "Departure " << setw(4) << setfill('0') << latestDeparture << ' ' << strDeparture << endl;
			cout << "Arrival   " << setw(4) << setfill('0') << earliestArrival << ' ' << strArrival << endl;

		}
		cout << endl;
	}
	return 0;
}
/*
2
3
Hamburg
Frankfurt
Darmstadt
3
2
0949 Hamburg
1006 Frankfurt
2
1325 Hamburg
1550 Darmstadt
2
1205 Frankfurt
1411 Darmstadt
0800
Hamburg
Darmstadt
2
Paris
Tokyo
1
2
0100 Paris
2300 Tokyo
0800
Paris
Tokyo
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值