PAT甲 - 1030 Travel Plan(Dijkstra + dfs)

题目

旅行者的地图给出了高速公路沿线城市之间的距离,以及每条高速公路的成本。现在您应该编写一个程序来帮助旅行者决定他/她的出发城市和目的地之间的最短路径。如果这样的最短路径不是唯一的,则应该输出成本最低的路径,该路径保证唯一。

输入

每个输入文件包含一个测试用例。每个案例以一行包含 4 个正整数 N、M、S 和 D 开始,其中 N (≤500) 是城市的数量(因此城市的编号从 0 到 N-1); M是高速公路的数量; S 和 D 分别是起始城市和目的地城市。然后是 M 行,每行提供一条高速公路的信息,格式为:

City1 City2 Distance(距离) cost(成本)

其中数字均为不超过 500 的整数,并以空格分隔。

输出

对于每个测试用例,一行打印从起点到终点的最短路径上的城市,然后是总距离和路径的总成本。数字必须用空格分隔,并且输出末尾不能有多余的空格。

解题思路

先用Dijkstra求一下最短路径,然后在判断最短路径的过程中给路径数组pre做记录,根据是小于还是大于做不同情况处理,然后dfs从后往前,根据路径数组pre来做处理,在最短路径相同的情况下做成本的判断。最后输出的时候由于push_back是路径从后往前的放的,输出的时候要从后往前输出。

由于写的时候没太注意,定义变量的时候名字比较随意,望体谅。

#include <iostream>
#include <vector>
#include<algorithm>
#define maxnum 999
using namespace std;
int n,m,s,d;
int minpath=maxnum;
int book[505]={0};
vector<vector<int>>v(505,vector<int>(505,maxnum));//路径长度
vector<vector<int>>pr(505,vector<int>(505,maxnum));//路径费用
vector<vector<int>>pre(505,vector<int>(505,maxnum));//存储路径
vector<int>temp,num;//存储最短路径
void dfs(int v){
	temp.push_back(v);
	if(v==s){
		int path=0;
        //遍历temp中的路径总成本并与之前的相同路径的成本做比较
		for(int i=0;i<temp.size()-1;i++){
			int price=temp[i],price2=temp[i+1];
			path+=pr[price][price2];
		}
		if(path<minpath){
			minpath=path;
			num=temp;
		}
		temp.pop_back();
		return;
	}
	for(int i=0;i<pre[v].size();i++){
		dfs(pre[v][i]);
	}
	temp.pop_back();
}

int main() {
	scanf("%d %d %d %d",&n,&m,&s,&d);
	for(int i=0;i<m;i++){
		int num,num1,len,price;
		cin>>num>>num1>>len>>price;
		v[num][num1]=len;
		v[num1][num]=len;
		pr[num][num1]=price;
		pr[num1][num]=price;
	}
	vector<int>dis(n,maxnum);
	dis[s]=0;
	for(int i=0;i<n;i++){
		int u=-1,num=maxnum;
		for(int j=0;j<n;j++){
			if(book[j]==0&&dis[j]<num){
				u=j;
				num=dis[j];
			}
		}
		if(u==-1)continue;
		book[u]=1;
		for(int j=0;j<n;j++){
			if(v[u][j]!=maxnum&&book[j]==0){
                //如果找到新的最短路径那就将之前储存的路径clear
				if(v[u][j]+dis[u]<dis[j]){
					dis[j]=v[u][j]+dis[u];
					pre[j].clear();
					pre[j].push_back(u);
				}
                //如果最短路径相等就直接储存,后续去dfs判断最小成本
				else if(v[u][j]+dis[u]==dis[j]){
					pre[j].push_back(u);
				}
			}
		}
	}
    //放入终点,从后往前寻找路径
	dfs(d);
	for(int i=num.size()-1;i>=0;i--){
		printf("%d ",num[i]);
	}
	printf("%d %d",dis[d],minpath);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值