CSU1232 懒汉的旅行 bfs+优先队列

32 篇文章 0 订阅

题目大意:懒汉需要从A城市开车到B城市去见一个朋友,他的汽车的邮箱的容积L升,车每行驶1公里就要消耗1升油。途中只有在到达一个城市之后才可以找的到加油站并加油,而且懒汉的车很特殊,每次加油只能加满整个邮箱。

懒汉希望途中加油的次数越少越好,当加油的次数相同时,他希望加油所花的钱数越少越好。现在懒汉把地图告诉了你,你能帮帮他吗?可以认为懒汉出发的时候油箱是满的,如果到达 B城市时油箱不是满的,也无需再加油。

假定各地加油站的汽油价格均为Y元/升,如果懒汉想从x城市沿长为z公里的路开车到达y城市,那么离开x城市时汽车至少应还有z升汽油。

Input
输入包含若干组数据,每组数据的第一行有四个正整数N(1<=N<=100),M(1<=M<=1000),L(1<=L<=100),Y(1<=Y<=100),其中N表示地图上一共有N个城市,标号分别为1,2,…,N,M表示N个城市间一共有M条路,L和Y的含义同上。

接下来一行有两个正整数S(1<=S<=N),T(1<=T<=N),分别表示A城市和B城市的标号。

接下来一共有M行,每行有三个正整数x(1<=x<=N),y(1<=y<=N),z(1<=z<=100),表示标号为x的城市和标号为y的城市之间有一条长为z公里的双向道路。

数据组数不超过100组,读入以EOF结束。

Output
对于每组数据,用一行输出一个整数,表示在加油次数最少的前提下,加油所花的最少的钱数。

如果懒汉不能开车到达B城市,输出-1即可。

Sample Input
4 4 6 1
1 4
1 2 3
2 4 4
1 3 2
3 4 6
Sample Output
2
思路:很明显要用到优先队列+bfs。(1)加油次数小的放在前面。(2)总花费少的放在前面。(3)剩余油量多的放在前面。关键是这题对于一个非终结状态最优判定是模糊的,比如说在同一个点 i i i,现在有三个状态:(1)加油次数 2 2 2,花费 120 120 120,剩余油量 0 0 0;(2)加油次数 3 3 3,花费 160 160 160;剩余油量 50 50 50;(3)加油次数 3 3 3,花费 200 200 200,剩余油量 100 100 100。设点 i i i距离终点的距离为 100 100 100公里,油价为 1 1 1元每公里,那么最优解其实是(3),次优解是(2),最差的解是(3)。是不是和自己预想的有些出入?因此这题对状态的筛选要宽松一点,只要加油次数、总花费、油量任意一个属性可更新,就应该把该状态放进队列中。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

struct Edge
{
	int to,nxt,dis;
}edge[2005];
int n,m,s,t,l,y,tot;
int head[105];

struct node
{
	int id,step,v,rest;
	node(){}
	node(int ii,int ss,int vv,int ll=l)
	{
		id=ii,step=ss,v=vv,rest=ll;
	}
	bool operator <(const node &a)const
	{
		if(step!=a.step)
			return step>a.step;
		if(v!=a.v)
			return v>a.v;
		if(rest!=a.rest)
			return rest<a.rest;
	}
}vis[105];

void addedge(int u,int v,int dis)
{
	edge[++tot].to=v,edge[tot].dis=dis,edge[tot].nxt=head[u],head[u]=tot;
}

void bfs()
{
	priority_queue<node> q;
	q.push(node(s,0,0));
	while(!q.empty())
	{
		node t1=q.top();
		q.pop();
		bool tag=0;
		if(t1.step<vis[t1.id].step)
			tag=1,vis[t1.id]=t1;
		else if(t1.v<vis[t1.id].v)
			tag=1,vis[t1.id]=t1;
		else if(t1.rest>vis[t1.id].rest)
			tag=1,vis[t1.id]=t1;
		if(!tag)
			continue;
		if(t1.id==t)
		{
			printf("%d\n",t1.v);
			return ;
		}
		for(int i=head[t1.id];i;i=edge[i].nxt)
		{
			if(edge[i].dis<=t1.rest)//不用加油
				q.push(node(edge[i].to,t1.step,t1.v,t1.rest-edge[i].dis));
			q.push(node(edge[i].to,t1.step+1,t1.v+(l-t1.rest)*y,l-edge[i].dis));
		}
	}
	printf("-1\n");
}
int main()
{
	while(~scanf("%d%d%d%d",&n,&m,&l,&y))
	{
		scanf("%d%d",&s,&t);
		int u,v,dis;
		tot=0;
		memset(head,0,sizeof(head));
		for(int i=1;i<=n;i++)
			vis[i]=node(i,INF,INF,0);
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&u,&v,&dis);
			if(dis>l)
				continue;
			addedge(u,v,dis),addedge(v,u,dis);
		}
		bfs();
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CSU飞跃手册2019是一个以服务学生发展为宗旨的学生服务项目,帮助学生实现个人成长和职业发展目标。飞跃手册提供了诸如成功学、职业规划、就业技巧以及个人发展等方面的指导,帮助学生掌握自我认知、提升职场竞争力并构建良好的人脉关系。 飞跃手册2019包括三个模块。第一个模块着重讲解如何探索自我,明确职业目标和规划职业道路。这些关键的步骤帮助学生发现自己的职业特长和兴趣爱好,从而为个人职业发展做出决策和规划。 第二个模块提供了职业发展过程中的必备技能,如招聘面试技巧、简历写作、职场沟通、决策和问题解决能力,以及管理和领导力等。这些技能帮助学生在职场中不断学习和成长,并展示自己的优势。 第三个模块则介绍如何利用社会资源和人脉关系来推动个人职业发展。它包括了网络管理、人脉建立、社交礼仪和社会责任等方面的指导。 总之,CSU飞跃手册2019是一份应对职场挑战和工作生涯的指南, 帮助学生建立自己的职业目标并实现自我发展。它讲解了个人成长、职场技能、人脉力量和社会责任等方面的内容,为学生的成功创造了一个强有力的支撑体系。 ### 回答2: CSU飞跃手册2019是一本由中国海洋大学控制科学与工程学院发行的指导学生爆炸性训练和实习的手册。该手册将学生分为不同职业兴趣组,并提供了具体的介绍、岗位培训以及实习就业方案。 该手册还包括了部分参考书目、学术论文和个人成长方向的建议,在实习期间指导学生更好地发展个人能力和提高自己的竞争力。除此之外,该手册还有一些校内外的实践活动介绍和经验分享。这些活动涵盖了多个不同领域,包括科技、创业、环保和社会公益等。 该手册还提供了一些面试技巧和求职指南,帮助学生更好地应对就业市场的挑战。此外,该手册还鼓励学生通过网络平台和社会实践等多种途径积累人脉资源,增强自己的社交和交际技巧。 总的来说,CSU飞跃手册2019为学生提供了一个全面的指导工具,帮助他们更好地理解职业规划,提高个人素质,扩展职业视野并实现自我价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值