描述
启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手柄。
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. IT回忆录-2

    随着网络的发展,下载工具也不断地更新. 印象比较深的下载工具,从网络蚂蚁.网际快车,到BT. BT出来的时候,对下载真的是一个革命啊,以前下载东西,下载的人越多肯定就越慢,我们之前还会跑到一些FTP上 ...

  2. Android零基础入门第15节:掌握Android Studio项目结构,扬帆起航

    原文:Android零基础入门第15节:掌握Android Studio项目结构,扬帆起航 经过前面的学习,Android Studio开发环境已准备OK,运行Android应用程序的原生模拟器和Ge ...

  3. C#高性能大容量SOCKET并发(九):断点续传

    原文:C#高性能大容量SOCKET并发(九):断点续传 上传断点续传 断点续传主要是用在上传或下载文件,一般做法是开始上传的时候,服务器返回上次已经上传的大小,如果上传完成,则返回-1:下载开始的时候 ...

  4. 在Windows IoT上生成和识别二维码

    在Windows IoT生成和识别二维码,实际上由于是UWP上实现,所以,理论上,这些生成和识别二维码的方法也可以在其它平台上运行. 关于二维码的生成有很多库可以实现,比如QRCoder,这个库可以在 ...

  5. RPG Maker MV游戏解包

    该文章最新版本请前往:https://www.crowsong.xyz/127.html 前言 使用Petschko's RPG-Maker-MV File-Decrypter进行解包 使用Petsc ...

  6. c# 关于TreeView的一点性能问题

    我们要知道,treeview在新增或删除treeNode的时候会进行重绘,这也就是为什么大量数据的时候,treeview很卡.很慢的原因, 那么我们这样 treeview1.BeginUpdate() ...

  7. qt+opencv对两幅图片进行融合

    本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 源代码: #include "widget.h" #include "ui ...

  8. Controls 属性与继承 TShape 类的小练习(使用TShape可以解决很多图形问题)

    本例效果图: 代码文件: unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, ...

  9. lodop+art-template实现web端漂亮的小票样式打印

    一. 现状 由于之前采用Lodop打印控件(商业版付费,可以使用免费版 但是会有水印)去打印小票,是一行一行的打印,但是不满足UI给到复杂布局的小票样式,所以得重新考虑如何来实现. 二. 介绍 art ...

  10. 机器学习-5 支持向量机SVM

    一.概念和背景 SVM:Support Vector Machine 支持向量机. 最早是由Vladimir N. Vapnik和Alexey Ya. Chervonenkis在1963年提出的. 目 ...