描述
启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手柄。
Nescafe之塔一共有N层,升降梯在每层都有一个停靠点。手柄有M个控制槽,第i个控制槽旁边标着一个数C_i,满足C1<C2<C3<...<CM。如果Ci>0,表示手柄扳动到该槽时,电梯将上升Ci层;如果Ci<0,表示手柄扳动到该槽时,电梯将下降 −Ci层;并且一定存在一个Ci=0,手柄最初就位于此槽中。注意升降梯只能在1~N层间移动,因此扳动到使升降梯移动到1层以下、N层以上的控制槽是不允许的。
电梯每移动一层,需要花费2秒钟时间,而手柄从一个控制槽扳到相邻的槽,需要花费1秒钟时间。探险队员现在在1层,并且想尽快到达N层,他们想知道从1层到N层至少需要多长时间?
输入
第一行两个正整数N、M。
第二行M个整数C_1、C_2、...、C_M。
输出
输出一个整数表示答案,即至少需要多长时间。若不可能到达输出-1。
输入样例 1
6 3
-1 0 2
输出样例 1
19
提示
数据范围:
1 <= n <= 1000
1 <= m <= 20 样例分析: 手柄从第二个槽扳到第三个槽(0扳到2),用时1秒,电梯上升到3层,用时4秒。
手柄在第三个槽不动,电梯再上升到5层,用时4秒。
手柄扳动到第一个槽(2扳到-1),用时2秒,电梯下降到4层,用时2秒。
手柄扳动到第三个槽(-1扳倒2),用时2秒,电梯上升到6层,用时4秒。
总用时为(1+4)+4+(2+2)+(2+4)=19秒。

这道题说实话,我刚做的时候看不出用什么办法来做。所以我选择了:

广搜!

每个状态分别为:当前楼层,花费时间,拉杆目前位置。

但是搜索一波出来发现:

只能过两组!

为什么呢?

很明显,光凭借广搜,我们无法一次得出最优的答案。所以我们就要考虑使用其他方法。

根据机房大佬和老师的帮助 ,这道题的正解是最短路!

那么怎么构图?

这就是这道题的核心问题。再次经过冥思苦想(确信),我们在二维的状态下,可以用dst[i][j]表示从拉杆位置在j时上到第i层所需要的时间。

但是二维的状态我们难以形成最短路。

那怎么办?

二维转一维!

直接写一个convert函数,把一个数对转换成一个编号。那么:

int convert(int x,int y)
{
return (x-1)*m+y;
}

接下来就是构图。

构图我的方法比较麻烦,用到了三层循环。大概代码如下:

for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=m;k++)
{
int u=convert(i,j),v=convert(i+c[k],k),w=abs(j-k)+abs(2*c[k]);
g[u].push_back(node(v,w));
}
}
}

因为我用到的是迪杰斯特拉算法(不了解的看看这篇博客再继续看下去哈),所以用到的是二维结构体vector来存图。前置定义如下

struct node
{
int v,w;
node(){}
node(int vv,int ww)
{
v=vv,w=ww;
}
};
vector<node> g[200010];

然后就可以用最短路模板来AC这道题目了,但是要注意的是,这道题的点数不是n,而是n*m!因为我们是把二维转成的一维,所以点数要乘上可能到达这个点的拉杆槽的数量!

最短路函数主体:

void dij(int p)
{
for(int i=1;i<=200010;i++)
{
dst[i]=INF;
s[i]=0;
}
s[p]=1;
dst[p]=0;
int lasti=p;
for(int k=1;k<n*m;k++)
{
for(int j=0;j<g[lasti].size();j++)
{
int v=g[lasti][j].v,w=g[lasti][j].w;
if(!s[v]&&dst[v]>w+dst[lasti])
{
dst[v]=w+dst[lasti];
}
}
int min_i=INF,min_dst=INF;
for(int i=1;i<=n*m;i++)
{
if(!s[i])
{
if(dst[i]<min_dst)
{
min_dst=dst[i];
min_i=i;
}
}
}
lasti=min_i;
s[min_i]=1;
}
}

最后一个问题:

我们最后输出啥?

最短路已经找出来,但是我们能直接输出dst[n]吗?

很明显不行!!!

我们的dst数组的每一个下标,对应的是一个数对,而不是一个点!

所以,我们要从以convert(n,1)为下标的dst值遍历到以convert(n,m)为下标的dst值,最后输出最小值即可。一个循环就可以搞定。

但是别忘了!题目中还有个输出"-1"的判断需求,需要注意的是,当我们无法到达第n楼的时候,对于任意一个小于m的i,dst[n] [convert(n,i)]的值是不会改变的!所以我们只需要在输出的时候判断一下ans是否有更新操作,没有就输出-1.

这一步代码如下:

int ans=INF;
for(int i=1;i<=m;i++)
{
int r=convert(n,i);
ans=min(ans,dst[r]);
}
if(ans!=INF)
cout<<ans<<endl;
else cout<<-1<<endl;

这是为了判断题中的特殊情况。

为了配合最终答案在 “无解” 的情况下dst[n]的任意值不会更新的特性,我们要在迪杰斯特拉的最外层循环的最后加上一句:

if(min_i==INF)return;
完整代码如下:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int c[1000010],n,m;
bool s[1000010];
int convert(int x,int y)
{
return (x-1)*m+y;
}
int dst[200010];
struct node
{
int v,w;
node(){}
node(int vv,int ww)
{
v=vv,w=ww;
}
};
vector<node> g[200010];
void dij(int p)
{
for(int i=1;i<=200010;i++)
{
dst[i]=INF;
s[i]=0;
}
s[p]=1;
dst[p]=0;
int lasti=p;
for(int k=1;k<n*m;k++)
{
for(int j=0;j<g[lasti].size();j++)
{
int v=g[lasti][j].v,w=g[lasti][j].w;
if(!s[v]&&dst[v]>w+dst[lasti])
{
dst[v]=w+dst[lasti];
}
}
int min_i=INF,min_dst=INF;
for(int i=1;i<=n*m;i++)
{
if(!s[i])
{
if(dst[i]<min_dst)
{
min_dst=dst[i];
min_i=i;
}
}
}
if(min_i==INF)return;
lasti=min_i;
s[min_i]=1;
}
} int main()
{
cin>>n>>m;
int now;
for(int i=1;i<=m;i++)
{
cin>>c[i];
if(c[i]==0)now=i;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=1;k<=m;k++)
{
int u=convert(i,j),v=convert(i+c[k],k),w=abs(j-k)+abs(2*c[k]);
g[u].push_back(node(v,w));
}
}
}
dij(convert(1,now));
int ans=INF;
for(int i=1;i<=m;i++)
{
int r=convert(n,i);
ans=min(ans,dst[r]);
}
if(ans!=INF)
cout<<ans<<endl;
else cout<<-1<<endl;
return 0;
}

ov.

【最短路算法例题-升降梯上】-C++的更多相关文章

  1. Dijkstra最短路算法

    Dijkstra最短路算法 --转自啊哈磊[坐在马桶上看算法]算法7:Dijkstra最短路算法 上节我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最 ...

  2. 10行实现最短路算法——Dijkstra

    今天是算法数据结构专题的第34篇文章,我们来继续聊聊最短路算法. 在上一篇文章当中我们讲解了bellman-ford算法和spfa算法,其中spfa算法是我个人比较常用的算法,比赛当中几乎没有用过其他 ...

  3. 【坐在马桶上看算法】算法7:Dijkstra最短路算法

           上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短路”.本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做“单源最短路径 ...

  4. 【坐在马桶上看算法】算法6:只有五行的Floyd最短路算法

            暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程.         上图中有 ...

  5. [Tyvj2032]升降梯上(最短路)

    [Tyvj2032]升降梯上 Description 开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道.一辆停在轨道底部的电梯.和电梯内一杆控制电梯升 ...

  6. Floyd最短路算法

    Floyd最短路算法 ----转自啊哈磊[坐在马桶上看算法]算法6:只有五行的Floyd最短路算法 暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计 ...

  7. Book 最短路算法

    用HDU2544整理一下最近学的最短路算法 1.Dijkstra算法 原理:集合S表示已经找到最短路径的点,d[]表示当前各点到源点的距离 初始时,集合里面只有源点,当每个点u进入集合S时,用d[u] ...

  8. 近十年one-to-one最短路算法研究整理【转】

    前言:针对单源最短路算法,目前最经典的思路即标号算法,以Dijkstra算法和Bellman-Ford算法为根本演进了各种优化技术和算法.针对复杂网络,传统的优化思路是在数据结构和双向搜索上做文章,或 ...

  9. 【啊哈!算法】算法7:Dijkstra最短路算法

    上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短路”.本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做“单源最短路径”.例如求下图 ...

随机推荐

  1. 对OO的封装了有了新的理解——希望是普通函数来写总体流程来统管类似的业务,但却又涉及具体操作的函数,仍然可以达到目的

    就是不厌其烦,把那个具体操作函数封装成虚函数,只需要返回它的结果就行.而总体流程根据这个结果继续进行处理,这样就能总体流程和虚函数两不误了.

  2. Windows下用VC与QT编译MPI程序入门

    MPI是信息传递接口的简称,常用来进行进程间.机器间的通信与并行计算.一般而言,MPI都会部署在*nix系统下,在Windows下面直接编译.配置MPI并不容易.本文利用MS提供的编译好的MPI的版本 ...

  3. 线程天敌TerminateThread与SuspendThread

    线程天敌TerminateThread与SuspendThread 作者:童磊(magictong) 目的:不是演示TerminateThread和SuspendThread的原理而是希望能在自己的程 ...

  4. Tensorflow 又要升级了。Nvidia驱动升级,牵一发而动全身

    如题. 以前好好的,在宿主主机上,升级了下Linux的内核到4.15.0-13 Ubuntu16.04 以前的nvidia 驱动竟然也调了.用tensorflow 的GPU加速,必须使用nvidia ...

  5. HTML连载7-表单练习

    昨天因为晚上有事情,未更新,但是今天中午发也不晚,因为是同一天只是时间早晚而已,因此今日傍晚还将更新一次,废话不多说. 1.表单的综合练习,我们要创建一个综合的注册页面.运用到我们前面所学的所有知识. ...

  6. Python 爬虫从入门到进阶之路(六)

    在之前的文章中我们介绍了一下 opener 应用中的 ProxyHandler 处理器(代理设置),本篇文章我们再来看一下 opener 中的 Cookie 的使用. Cookie 是指某些网站服务器 ...

  7. Spark学习之路(一)—— Spark简介

    一.简介 Spark于2009年诞生于加州大学伯克利分校AMPLab,2013年被捐赠给Apache软件基金会,2014年2月成为Apache的顶级项目.相对于MapReduce的批处理计算,Spar ...

  8. python基础(1)--input print if else elif while 用法说明

    1 变量名的命名规则: 由数字,字母和下划线组成,但是不能以数字开头命名变量.例如 a ,b ,c ,name ,user1 user_id 等都可作为变量名称. 1a,2b 3cd等都不行.特别注意 ...

  9. 长春理工大学第十四届程序设计竞赛(重现赛)J

    J.Printout 题目:链接:https://ac.nowcoder.com/acm/contest/912/J 题目: 小r为了打校赛,他打算去打字社打印一份包含世界上所有算法的模板. 到了打字 ...

  10. SpringBoot(十九)_404返回统一异常处理结果

    之前写过一篇统一异常处理的文章,今天测试了下如果访问一个不存在的接口,也想返回统一的错误信息,应该怎么做 1.修改application.properties文件 # 自定义404 #出现错误时, 直 ...