《算法竞赛指南》0x6B 升降梯上

升降梯上

大意

n层塔,m个按钮,每次拉拉杆上下电梯,拉拉杆需1s,上下一层需2s,求最小的上升到顶层的时间

思路

虽然看起来不像,但我们可以用最短路中的分层图来思考,遍历每个点以及每个拉杆所上下的楼层,将当前楼层与拉过拉杆所在的楼层相连接,权值为拉杆的位置,连完边之后,跑一遍dijkstra求出最短路即可。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=108600;
struct note
{
	int to,next,val;
}edge[N];
int head[N],cnt=0;
void add(int x,int y,int z)
{
	edge[++cnt].to=y;
	edge[cnt].val=z;
	edge[cnt].next=head[x];
	head[x]=cnt;
}
LL dis[N],bs[N];
bool vis[N];
priority_queue<pair<int,int> > q;
int n,m,c[N],ss;
void dij()
{
	for(int i=1;i<=1086;i++) dis[i]=100086;
	memset(vis,0,sizeof(vis));
	dis[1]=0;
	bs[1]=ss;
	q.push(make_pair(0,1));
	while(q.size())
	{
		int x=q.top().second;
		q.pop();
		if(vis[x]==1) continue;
		vis[x]=1;
		int now=bs[x];
		for(int i=head[x];i;i=edge[i].next)
		{
			int y=edge[i].to;
			if(dis[y]>dis[x]+2*abs(y-x)+abs(edge[i].val-now))
			{
				dis[y]=dis[x]+2*abs(y-x)+abs(edge[i].val-now);
				bs[y]=edge[i].val;
				q.push(make_pair(-dis[y],y));
			}
		}
	}
	
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&c[i]);
		if(c[i]==0) ss=i;
	} 
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i+c[j]<=0||i+c[j]>n||c[j]==0) continue;
			add(i,i+c[j],j);
		}
	}
	dij();
	if(dis[n]!=100086) printf("%d\n",dis[n]);
	else printf("-1\n");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值