西北大学2019年春季校赛 ( 重现赛 )G.房间迷宫

博客描述了一个迷宫问题,鸡尾酒被困迷宫,从1号房到n号房,进入房间需缴过路费,还可花钱开箱子移动。要求计算走出迷宫的最小花费,若无法走出则输出 -1。给出输入输出描述及样例,还提及可用最短路算法如dij、spfa求解。

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

题目地址

题目描述

 

鸡尾酒被困入了一个迷宫!

这个迷宫总共有n个房间组成,鸡尾酒初始在1号房间,n号房间为迷宫的出口。每进入一次第i个房间都需要缴纳ai的过路费(包括初始的一号房间)。每个房间有一张纸条和一个箱子。纸条上写着的数字di代表鸡尾酒下一个可以到达的房间编号。

鸡尾酒也可以选择花费bi的金钱打开箱子,箱子中有一个密码ci,打开箱子之后鸡尾酒可以移动到i+k号房间,其中c可被k整除。但如果i+k>n,则不能移动。

求鸡尾酒从走出迷宫的最小花费。若鸡尾酒无法走出迷宫,输出-1。

输入描述

 

输入第一行一个n,代表迷宫共有n个房间(n<2e5)

接下来有n行,每行包含四个整数ai,bi,ci,di,意义如题面所描述。其中(ai,bi,ci,di≤2e5)

输出描述

 

输出一行一个整数代表走出迷宫的最小花费。

样例输入 1 

5
1 2 2 4
2 2 2 2
1 1 2 2
100 1 1 1
1 1 1 1

样例输出 1

6

最短路板子,图已经在数据中建好,只需要在dij中处理开宝箱得花费和进入房间得费用最小即可

 

//没有建图得操作是因为数据中已经给建好了房间得联通关系
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 210000;
const ll inf = 1e15;
int a[maxn],b[maxn],c[maxn],d[maxn];
bool vis[maxn];
ll dis[maxn];//存储到第i个房间得花费
int n,m;
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
void dij(int s)
{
	for (int i=1;i<=n;++i)
	{
		dis[i]=inf;
		vis[i]=0;
	}

	dis[s]=a[1];
	for (int i=1;i<=n;++i)
		q.push(make_pair(dis[i],i));
	while (!q.empty())
	{
		int u=q.top().second;
		q.pop();
		if (vis[u]) continue ;
		vis[u]=1;
		if (dis[d[u]]>dis[u]+a[d[u]]) {//将直接进入房间的花费更新到dis数组里
			dis[d[u]]=dis[u]+a[d[u]];
			q.push(make_pair(dis[d[u]],d[u]));
		}
		for (int i=1;i*i<=c[u];i++)//因为有c能被k整除的条件,并且2e5的数据也不大,直接遍历找到c的因子,判断是否会超过最后一个房间,并将花费更新进dis数组
		{
			if (c[u]%i==0)
			{
				int dd=i;
				if (dd+u<=n)
				{
					if (dis[dd+u]>dis[u]+a[dd+u]+b[u])
					{
						dis[dd+u]=dis[u]+a[dd+u]+b[u];
						q.push(make_pair(dis[dd+u],dd+u));
					}
				}
				dd=c[u]/i;
				if (dd+u<=n)
				{
					if (dis[dd+u]>dis[u]+a[dd+u]+b[u])
					{
						dis[dd+u]=dis[u]+a[dd+u]+b[u];
						q.push(make_pair(dis[dd+u],dd+u));
					}
				}
			}
		}
	}
}
int main() {

	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i]>>c[i]>>d[i];
	}
	dij(1);
	if(dis[n]==inf) cout<<-1<<endl;
	else cout<<dis[n]<<endl;
	return 0;
}

 也可以用spfa,也是板子操作。。留坑

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值