1030 Travel Plan (30 point(s))

本文介绍了一道PAT竞赛题目“旅行计划”的解决方案,该题要求找出从起点到终点的最短路径,并在路径不唯一时选择成本最低的路径。文章详细解析了Dijkstra算法在解决此类问题中的应用,包括如何回溯路径、定义构造函数以及实现关键步骤。

1030 Travel Plan (30 point(s))

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); M is 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

思路和1087 All Roads Lead to Rome基本一致,属于PAT常见题型。考点:Dijkstra算法灵活应用。

注意点:

1. DFS回溯路径的方法,深刻理解递归。

2. 注意构造函数定义。

#include<iostream>
#include<vector>
#include<cstring>
#define MAX 0x3f3f3f3f
using namespace std;
int N,M,S,D;
const int LEN = 505;
struct Edge{
	int next;int weight;int cost;//下一个结点、距离、花销 
	Edge(int n,int w,int c):next(n),weight(w),cost(c){	}
};
vector<Edge>graph [LEN];
int dis[LEN];//记录距离 
int sumCost[LEN];//当前总花销 
int last[LEN];//记录上一个城市 
bool visit[LEN]={false};
void dfs(int x){
	if(x==S){
		cout<<x;return;
	} 
	dfs(last[x]);
	cout<<" "<<x;
}
int main(void){
	cin>>N>>M>>S>>D;
	int a,b,w,c;
	for(int i=0;i<M;i++){
		cin>>a>>b>>w>>c;
		graph[a].push_back(Edge(b,w,c));
		graph[b].push_back(Edge(a,w,c));
	}
	memset(dis,-1,sizeof(dis));
	
	int newP = S;
	visit[newP] = true;
	dis[newP] = 0;
	while(!visit[D]){
		for(int i=0;i<graph[newP].size();i++){
			int v = graph[newP][i].next;
			int w = graph[newP][i].weight;
			int c = graph[newP][i].cost;
			if(visit[v]) continue;
			if(dis[v]==-1||dis[newP]+w<dis[v]){//不可达或者有更近的路径 
				dis[v] = dis[newP]+w;//更新距离 
				sumCost[v] = sumCost[newP]+c;//更新消耗
				last[v] = newP;//更新前驱城市 
			}
			else if(dis[newP]+w==dis[v]&&sumCost[newP]+c<sumCost[v]){//距离相等但是有更小的消耗 
				sumCost[v] = sumCost[newP]+c;//更新消耗
				last[v] = newP;//更新前驱城市 				
			} 
		}
		int min = MAX;
		for(int i=0;i<N;i++){
			if(dis[i]==-1) continue;
			if(visit[i]) continue;
			if(dis[i]<min){
				min = dis[i];
				newP = i;
			}
		} 
		visit[newP] = true;
	}
	dfs(D);
	cout<<" "<<dis[D]<<" "<<sumCost[D]<<endl;
	return 0;
}

 

<launch> <!-- size of map, change the size in x, y, z according to your application --> <arg name="map_size_x" value="40.0"/> <arg name="map_size_y" value="20.0"/> <arg name="map_size_z" value=" 5.0"/> <!-- topic of your odometry such as VIO or LIO --> <arg name="odom_topic" value="/state_ukf/odom" /> <!-- main algorithm params --> <include file="$(find plan_manage)/launch/kino_algorithm.xml"> <arg name="map_size_x_" value="$(arg map_size_x)"/> <arg name="map_size_y_" value="$(arg map_size_y)"/> <arg name="map_size_z_" value="$(arg map_size_z)"/> <arg name="odometry_topic" value="$(arg odom_topic)"/> <!-- camera pose: transform of camera frame in the world frame --> <!-- depth topic: depth image, 640x480 by default --> <!-- don't set cloud_topic if you already set these ones! --> <arg name="camera_pose_topic" value="/pcl_render_node/camera_pose"/> <arg name="depth_topic" value="/pcl_render_node/depth"/> <!-- topic of point cloud measurement, such as from LIDAR --> <!-- don't set camera pose and depth, if you already set this one! --> <arg name="cloud_topic" value="/pcl_render_node/cloud"/> <!-- intrinsic params of the depth camera --> <arg name="cx" value="321.04638671875"/> <arg name="cy" value="243.44969177246094"/> <arg name="fx" value="387.229248046875"/> <arg name="fy" value="387.229248046875"/> <!-- maximum velocity and acceleration the drone will reach --> <arg name="max_vel" value="3.0" /> <arg name="max_acc" value="2.0" /> <!-- 1: use 2D Nav Goal to select goal --> <!-- 2: use global waypoints below --> <arg name="flight_type" value="1" /> <!-- global waypoints --> <!-- If flight_type is set to 2, the drone will travel these waypoints one by one --> <arg name="point_num" value="2" /> <arg name="point0_x" value="19.0" /> <arg name="point0_y" value="0.0" /> <arg name="point0_z" value="1.0" /> <!-- set more waypoints if you need --> <arg name="point1_x" value="-19.0" /> <arg name="point1_y" value="0.0" /> <arg name="point1_z" value="1.0" /> <arg name="point2_x" value="0.0" /> <arg name="point2_y" value="19.0" /> <arg name="point2_z" value="1.0" /> </include> <!-- trajectory server --> <node pkg="plan_manage" name="traj_server" type="traj_server" output="screen"> <remap from="/position_cmd" to="planning/pos_cmd"/> <remap from="/odom_world" to="$(arg odom_topic)"/> <param name="traj_server/time_forward" value="1.5" type="double"/> </node> <node pkg="waypoint_generator" name="waypoint_generator" type="waypoint_generator" output="screen"> <remap from="~odom" to="$(arg odom_topic)"/> <remap from="~goal" to="/move_base_simple/goal"/> <remap from="~traj_start_trigger" to="/traj_start_trigger" /> <param name="waypoint_type" value="manual-lonely-waypoint"/> </node> <!-- use simulator --> <include file="$(find plan_manage)/launch/simulator.xml"> <arg name="map_size_x_" value="$(arg map_size_x)"/> <arg name="map_size_y_" value="$(arg map_size_y)"/> <arg name="map_size_z_" value="$(arg map_size_z)"/> <arg name="c_num" value="10"/> <arg name="p_num" value="150"/> <arg name="odometry_topic" value="$(arg odom_topic)" /> </include> </launch>详细解释一下并说明和上个文件的不同
最新发布
08-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值