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

Posted zero_orez6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法竞赛指南》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;
}

以上是关于《算法竞赛指南》0x6B 升降梯上的主要内容,如果未能解决你的问题,请参考以下文章

算法竞赛进阶指南做题记录

实验13读后感:《算法竞赛进阶指南》

题解|《算法竞赛进阶指南》 Sticks

算法竞赛训练指南11.2 最小生成树

算法竞赛进阶指南基本算法:递推与递归

《算法竞赛进阶指南》图论习题