7-15 天梯地图 (30 分)

本文详细介绍了一种解决双目标最短路径问题的算法,即同时考虑时间和距离两个因素的最短路径寻找方法。通过使用两次Dijkstra算法,分别以时间和距离作为权重,算法能够找到从起点到终点的最快路径和最短路径。最后,算法比较两种路径的一致性,如果一致则输出单一路径,如果不一致,则分别输出最快路径和最短路径。

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

传送门

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<stack>
#define ll long long
#define N 0x3f3f3f3f
using namespace std;
int f1[501],f2[501],ti[501][501],co[501][501];
int x,y,z,d,t,cnt[501],s,e,n,m,i,j;
int vis[501];
int ss[501];
int sss[501];
int tt[501];
void dijsktra1(int x)
{
	memset(vis,0,sizeof(vis));
	for(int i=0;i<n;i++)
	{
		ss[i]=N;
	}
	ss[x]=0;
	for(int i=0;i<n;i++)
	{
		int u=-1;
		int minn=N;
		for(int j=0;j<n;j++)
		{
			if(!vis[j]&&minn>ss[j])
			{
				u=j;
				minn=ss[j];
			}
		}
		if(u==-1)
		break;
		vis[u]=1;
		for(int j=0;j<n;j++)
		{
			if(!vis[j]&&ss[j]>ss[u]+co[u][j])
			{
				cnt[j]=cnt[u]+1;
				ss[j]=ss[u]+co[u][j];
				f1[j]=u;
			}
			else if(!vis[j]&&ss[j]==ss[u]+co[u][j])
			{
				if(cnt[j]>cnt[u]+1)
				{
					f1[j]=u;
					cnt[j]=cnt[u]+1;
				}
			}
		}
	}
}
void dijsktra2(int x)
{
	memset(vis,0,sizeof(vis));
	for(int i=0;i<n;i++)
	{
		sss[i]=N;
	}
	sss[x]=0;
	for(int i=0;i<n;i++)
	{
		int u=-1;
		int minn=N;
		for(int j=0;j<n;j++)
		{
			if(!vis[j]&&minn>sss[j])
			{
				u=j;
				minn=sss[j];
			}
		}
		if(u==-1)
		break;
		vis[u]=1;
		for(int j=0;j<n;j++)
		{
			if(!vis[j]&&sss[j]>sss[u]+ti[u][j])
			{
				sss[j]=sss[u]+ti[u][j];
				ss[j]=ss[u]+co[u][j];
				f2[j]=u;
			}
			else if(!vis[j]&&sss[j]==sss[u]+ti[u][j])
			{
				if(ss[j]>ss[u]+co[u][j])
				{
					f2[j]=u;
					ss[j]=ss[u]+co[u][j];
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		cnt[i]=1;
		for(int j=0;j<n;j++)
		{
			ti[i][j]=N;
			co[i][j]=N;
		}
	}
	for(int i=1;i<=m;i++)
	{
		cin>>x>>y>>z>>d>>t;
		if(z==1)
		{
			ti[x][y]=t;
			co[x][y]=d;
		}
		else
		{
			ti[x][y]=ti[y][x]=t;
			co[x][y]=co[y][x]=d;
		}
	}
	cin>>s>>e;
	dijsktra1(s);
	stack<int>ss1,ss2;
	int k1=e;
	ss1.push(k1);
	int len1=ss[e];
	while(f1[k1]!=s)//一开始我写的是 !=0 发现总是多输出一次起点 然后就想着输出前T出一个 就行了 
                    //发现有两个样例过不了。。好迷啊
	{
		ss1.push(f1[k1]);
		k1=f1[k1];
	}
	memset(vis,0,sizeof(vis));
	dijsktra2(s);
	int k2=e;
	int len2=sss[e];
	ss2.push(k2);
	while(f2[k2]!=s)//同上
	{
		ss2.push(f2[k2]);
		k2=f2[k2];
	}
	if(ss1==ss2)
	{
		printf("Time = %d; Distance = %d: %d",len2,len1,s);
		while(!ss1.empty())
		{
			printf(" => %d",ss1.top());
			ss1.pop();
		}
	}
	else
	{
		printf("Time = %d: %d",len2,s);
		while(!ss2.empty())
		{
			printf(" => %d",ss2.top());
			ss2.pop();
		}
		puts("");
		printf("Distance = %d: %d",len1,s);
		while(!ss1.empty())
		{
			printf(" => %d",ss1.top());
			ss1.pop();
		}
	}
	return 0;
}

 

### L3-007 天梯地图算法解析 #### Dijkstra算法的应用背景 在解决L3-007天梯地图这一编程挑战时,核心在于理解和运用Dijkstra算法来处理加权图中的最短路径问题。此题不仅考察基本的最短路径求解方法,还进一步要求能够区并提供两种不同类型的最优路径——即最快到达时间和最短物理距离下的路径[^1]。 #### 数据结构的选择与初始化 为了高效地存储和访问节点间的关系以及权重信息,通常会选择邻接表作为底层数据结构。对于每一个查询请求而言,程序需读取起点(队员所在位置)和终点(比赛场地),并将这些信息映射到预先构建好的城市网络模型中去。此外,还需准备两个优先级队列别用于保存当前已知的最佳时间成本和空间成本路径状态[^2]。 #### 计算过程详解 当执行具体计算逻辑时,应先通过一次完整的Dijkstra遍历找到从源点出发至目标点之间的最小累积耗时方案;紧接着再独立运行第二次迭代专注于寻找总行程长度上的极小化解答。值得注意的是,在每次松弛操作期间除了更新相应的代价外还需要同步维护额外的状态变量用来追踪经过了多少个中间站点以便后续输出完整的结果集[^4]。 ```python import heapq def dijkstra(graph, start, end, mode='time'): n = len(graph) dist = [float('inf')] * n prev = [-1] * n count = [0] * n pq = [(0, start)] while pq: d, u = heapq.heappop(pq) if u == end or d > dist[u]: continue for v, w in graph[u]: alt = d + (w[mode=='distance']) if alt < dist[v]: dist[v], prev[v], count[v] = alt, u, count[u]+1 heapq.heappush(pq,(alt,v)) path = [] node = end while node != -1: path.append(node) node = prev[node] return {'path': list(reversed(path)), 'cost': dist[end], 'nodes_passed':count[end]} ``` 上述代码实现了基于给定模式(`'time'` 或 `'distance'`)选择合适边权进行单源最短路搜索的功能,并返回包含所选路径、对应开销及途经顶点数量在内的字典对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值