c++搜索类型训练题——探望朋友——伟大的旭哥的博客

该博客介绍了一种使用回溯法解决在有限预算内从起点到终点的最短公交换乘路径问题。文章详细阐述了算法的实现,包括剪枝策略和记忆化搜索,以提高搜索效率。在给定的输入样例中,通过搜索所有可能的路径,找到了最短的公交路线。

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

题目描述

小科和他的朋友小丁都住在科丁市,科丁市有N个小区,编号为1...N,小科住在小区1,小丁住在小区N。有M班公交在这N个小区之间穿梭,每班公交都有一个出发小区S和一个终点小区D,以及从S到D的路程和票价。(途中不会经过其他小区)。有一天小科想要去拜访小丁,但是他只有K元钱,请帮助小科找出从他所在的小区1乘坐公交到达小丁所在的小区N,在总花费不超过K的前提下,路程最短的公交换乘线路。

输入格式

第1行:3个空格分隔的整数,分别表示小科拥有的钱数K(0 <= K <= 10000),科丁市的小区数量N(1 <= N <= 100),以及科丁市的公交班次M(1 <= M <= 10000)。

接下来M行:每行4个空格分隔的整数,表示一班公交的信息,其中第i行的4个整数分别表示第i班公交的起点小区S,终点小区D(1 <= S, D <= N)、行驶路程L(1 <= L <= 100) 和所需花费C(0 <= C <= 100)。(注意:从S到D的公交并不能从D到S,同时两个城市之间可能有多个不同路程和价格的公交班次)。

输出格式

1行:一个整数,表示在总花费不超过K的前提下,小科要从小区1到达小区N的最短路程,如果无法到达小区N,则输出-1。

输入输出样列

输入样例1:

5 6 7 1 2 2 3 2 4 3 3 3 4 2 4 1 3 4 1 4 6 2 1 3 5 2 0 5 4 3 2

输出样例1:

11

【耗时限制】1000ms 【内存限制】128MB

做题思路:定义问题的解:花费不超过K元的从源城市1到目标城市的一条路径构成问题的一个解。

回溯法:搜索所有可能路径,其中距离最小的一条即是问题的解

到达目的地:N就到达了路径的目的地。

可选范围:对于任一城市i,以i为起点的公交班次都可以选择。

剪枝优化:

① 可行性剪枝:如果当前正在搜索的路径所需花费已经超过了K,则剪枝。

② 最优化剪枝:如果当前正在搜索的路径长度 ≥ 已搜出的完整路径的长度,则剪枝。

记忆化剪枝:对于任意城市i:

① 如果当前路径到达i的花费和之前某次到达i的花费相同,但路程更长,则剪枝。

② 如果当前路径到达i的路程和之前某次到达i的路程相同,但花费更多,则剪枝。

完整代码:

#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans=0x3F3F3F3F,INF=0x3F3F3F3F;
bool vis[105];
struct road
{
	int d,l,c;
}r;
vector<road> g[105];
void dfs(int cur,int len,int cost)
{
	if(cost>k||len>=ans) return;
	if(cur==n)
	{
		ans=len;
		return;
	}
	for(int i=0;i<g[cur].size();i++)
	if(!vis[g[cur][i].d])
	{
		vis[g[cur][i].d]=true;
		dfs(g[cur][i].d,len+g[cur][i].l,cost+g[cur][i].c);
		vis[g[cur][i].d]=false;
	}
}
int main()
{
	cin>>k>>n>>m;
	int s;
	for(int i=1;i<=m;i++)
	{
		cin>>s>>r.d>>r.l>>r.c;
		g[s].push_back(r);
	}
	dfs(1,0,0);
	if(ans<INF) cout<<ans;
	else cout<<"-1";
}

感谢大家阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值