[图论][最短路]步行

题目描述

ftiasch又开发了一个奇怪的游戏,这个游戏是这样的:有N个格子排成一列,每个格子上有一个数字,第i个格子的数字记为Ai。这个游戏有2种操作:
1.如果现在在第i个格子,则可以跳到第Ai个格子。
2.把某个Ai增加或减少1。
nm开始在第1个格子,他需要走到第N个格子才能通关。现在他已经头昏脑涨啦,需要你帮助他求出,从起点到终点最少需要多少次操作。

输入

第1行,1个整数N。第2行,N个整数Ai。

输出

第1行,1个整数,表示最少的操作次数。

样例输入

5
3 4 2 5 3

样例输出

3

提示

?对于30%的数据,1≤N≤10。
?对于60%的数据,1≤N≤1,000。
?对于100%的数据,1≤N≤100,000,1≤Ai≤N。

题目大意:很清楚了,就不解释了。

思路:建立图模型(如下),会发现其实等价于求起点到终点的最短路(bfs或几种最短路算法)。

(样例:3 4 2 5 3,起点1,终点5,答案3)

(样例:3 3 3 3 3 ,起点1,终点5,答案3)

如何建立此图模型:

1.建立起i到Ai的单向边,权值为1,表明从i到Ai需要操作1步;

2.建立起i与i-1(如果存在的话),i与i+1(如果存在的话)的双向边,权值也都为1;

(比如说有a[2]=4,那么不光要建立2到4的单向边,也要建立4与3,4与5的双向边)

这个要好好理解,根据题意,可以对任意Ai加或减1,并算做一步操作,于是可以理解为:虽然a[2]=4(也就是2可以跳到4),但对a[2]进行加减1操作后,就意味着2也可以到3或5,当然操作数数也要加上1,所以建立相邻数的双向边意思是相邻数其实可以互通(对应着加减1操作),比如有a[2]=4,a[4]=1的话,当2跳到4后,4可以跳到1,3或5,同理接着5(假如上一步跳到了5)可以跳到a[5],4或者6...,那么从2到6的过程可以看作是2->4->5->6(等价于把a[2]加1再加1变成6后跳到6)。

可以自己再琢磨一下上面两个图。

还有需要明白的是,对于所在位置i的下一位置a[i],i-1,i+1在bfs中属于同一层。

注意(!):

在bfs中起点不能是1,因为这样的话a[1]和2将被1更新并被加入队列,“更新”也就是1->a[1]使到达a[1]的最少步数f[a[1]]变为f[1]+1=0+1=1,同理1->2使得f[2]变为f[1]+1=1,答案显然是不对的(因为按此法要2步操作),所以起点1处有点特殊,不能用它来更新2(即不能从head=1(f[head]=0)开始进行bfs),所以我们从head=a[1](f[head]=1)开始进行bfs。

AC代码:

#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
int n;
int a[100010];
int f[100010];
int vis[100010];

void bfs(){
  queue<int > q;
  while(!q.empty()) q.pop();
  f[1]=0;
  vis[1]=1;
  int head=a[1];
  f[head]=1;
  vis[head]=1;
  q.push(head);
  while(!q.empty()){
    head=q.front();
    q.pop();
    if(!vis[a[head]]){
        vis[a[head]]=1;
        if(f[a[head]]>f[head]+1)
            f[a[head]]=f[head]+1;
        q.push(a[head]);
    }
    if(head-1>=1&&!vis[head-1]){
        vis[head-1]=1;
        if(f[head-1]>f[head]+1)
            f[head-1]=f[head]+1;
        q.push(head-1);
    }
    if(head+1<=n&&!vis[head+1]){
        vis[head+1]=1;
        if(f[head+1]>f[head]+1)
            f[head+1]=f[head]+1;
        q.push(head+1);
    }
  }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    memset(vis,0,sizeof(vis));
    memset(f,inf,sizeof(f));
    bfs();
    printf("%d\n",f[n]);
    return 0;
}

总结:对于图论题,关键是等价建立图模型。

原文地址:https://www.cnblogs.com/lllxq/p/8432635.html

时间: 2024-10-08 20:40:35

[图论][最短路]步行的相关文章

bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集

bzoj4144 [AMPPZ2014]Petrol 图论 最短路 并查集 1.这道题我们主要就是要求出距离一个油站的最近的油站 首先我们dijkstra 求出任意一个点到 离他最近的油站的距离 2.然后会发现 如果一条边的两个端点 的最近油站不同的话 那么这条边就会在这两个油站的最短路上 3.然后对于每一条边 我们将他的权值 变为 dis[ u ] + dis[ v ] + e[ i ][ j ] 如果u与v最近油站相同 那么这个无意义 如果不同 那么久表示 u 最近油站 到 v 最近油站的最

POJ 3259 Wormholes (图论---最短路 Bellman-Ford || SPFA)

链接:http://poj.org/problem?id=3259 Description While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BE

HDU 5521 [图论][最短路][建图灵感]

/* 思前想后 还是决定坚持写博客吧... 题意: n个点,m个集合.每个集合里边的点是联通的且任意两点之间有一条dis[i]的边(每个集合一个dis[i]) 求同时从第1个点和第n个点出发的两个人相遇的最短时间,并输出相遇的地点,如果有多个按编号大小顺序输出. 输入: 测试数据 t n m 以下m行每行 dis[i] 该集合点的数量 ...每个点的标号 数据范围: n 2-1e5 所有集合的元素的数量和 1e6 思路: 如果直接跑最短路,边会存爆的. 考虑换种思路建边. 每个集合看作两个点,一

图论 最短路 基础

图论基础 , 最短路 图的简单概念 顶点 (Vertex), 边 (Edge) 有向图 , 无向图 , 无向图是一种特殊的有向图 度,有向图分为出度 和 入度,无向图的度,代表 连出去的边 顶点和边都可以具有属性,称为权重,顶点称为 点权,边 称为 边权 稠密图 边很多,大约是 顶点的平方 稀疏图 边很少 , 重边(平行边),自环, 路径:从一给顶点到达另一个顶点称为一条路径 路径中边的数量称为路径长度,如果路径中的顶点均不重复,称为简单路径 如果路径中的第一个顶点 \(v_i\) 和最后一个顶

洛谷P1027 Car的旅行路线 计算几何 图论最短路

题意 求某城到某城的最小花费 一个城中有四个机场,一个城中的机场相互可达,用公路到达,但是不同城的公路的单位路程的费不同,两个不同城的机场(我不知道相同城可不可以)可以通过机场到达,且飞机单位路程价格一定,问从 a 城到b城的最小花费,可从a的任一机场出发,从 b 的任一机场结束 . 题解 这道题思路还算容易,就是求最短路,只是建图比较麻烦, 总体思路 1.建图(1) 相同城 的四个机场两两连线 求距离, [1]但是他只给出了三个点,也就是说这第四个点要我们自己求 首先他给出三个点,这三个点一定

图论——最短路

Tyvj 1221 微子危机——战略 背景 №.3Summer联盟战前兵力战略转移. 描述 Summer的兵力分布在各个星球上,现在需要把他们全部转移到某个星球上.Summer一共拥有N个星球(1-N),你要把这N个星球上的兵力转到第M个星球上.本来每个星球之间都有星际轨道连接,但Guiolk监视了某些轨道,我们一但走上这些轨道,有可能受到他的攻击.为了安全,Summer不会走被监视的轨道.于是,只有L个星际轨道是被批准通过的.Summer的国防部想统计一下所需的最短路程(即每个星球到第M星球的

图论——最短路②

RT 最短路计数 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶点数与边数. 接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边. 输出格式: 输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可.如果无法到达顶点i则输出0. 样例 输入: 输出

图论——最短路①

RT 找工就业 Bessie is running out of money and is searching for jobs. Farmer John knows this and wants the cows to travel around so he has imposed a rule that his cows can only make D (1 <= D <= 1,000) dollars in a city before they must work in another

[图论]最短路系列

昨天今天两天复习了一下最短路, 1 Floyd 2 Dijkstra 3 Bellman-ford 4 (SPFA) (但是还有一些其他的比如:第k短路,Johnson,差分约束没有仔细研究过) Dijkstra堆优化 luogu3371 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三个整数Fi.Gi.Wi,分别表示第i条有向边的出发点.目标点