题目链接

A robot has to patrol around a rectangular area which is in a form of m × n grid (m rows and n columns). The rows are labeled from 1 to m. The columns are labeled from 1 to n. A cell (i, j) denotes the cell in row i and column j in the grid. At each step, the robot can only move from one cell to an adjacent cell, i.e. from (x, y) to (x + 1, y), (x, y + 1), (x − 1, y) or (x, y − 1). Some of the cells in the grid contain obstacles. In order to move to a cell containing obstacle, the robot has to switch to turbo mode. Therefore, the robot cannot move continuously to more than k cells containing obstacles. Your task is to write a program to find the shortest path (with the minimum number of cells) from cell (1, 1) to cell (m, n). It is assumed that both these cells do not contain obstacles.

Input
The input consists of several data sets. The first line of the input file contains the number of data sets which is a positive integer and is not bigger than 20. The following lines describe the data sets. For each data set, the first line contains two positive integer numbers m and n separated by space (1 ≤ m, n ≤ 20). The second line contains an integer number k (0 ≤ k ≤ 20). The i-th line of the next
m lines contains n integer aij separated by space (i = 1, 2, . . . , m; j = 1, 2, . . . , n). The value of aij is ‘1’ if there is an obstacle on the cell (i, j), and is ‘0’ otherwise.

Output
For each data set, if there exists a way for the robot to reach the cell (m, n), write in one line the integer number s, which is the number of moves the robot has to make; ‘-1’ otherwise.

1.题目大意:有一个m*n的网格,一个机器人要从网格的左上角(1,1)走到右下角(m,n)。网格中输入的0代表空地可以直接通过,1代表障碍代表不能通过。但是现在题目中给出一个k代表机器人能连续翻越障碍的最大值,求最短路长度,起点终点保证是空地

2.我刚开始想的是设置一个全局变量k和一个标志前一次是否走过障碍的变量flag。BFS开始前令一个局部变量res等于k,每次如果走到了空地,比平时多判断一下上一次是否走了障碍,如果上一次走了障碍再把res设置为k表示下次还能连续走k次障碍 flag设置为0表示这次走了空地。当走到障碍时,判断res是否大于0,大于0代表能直接走,接着判断是否上一步是否是空地,如果是空地就设置这一步走了障碍。尽管感觉上面思路有一定的可行性,但是WA了,应该是由于BFS并不向DFS那样一路搜到底,就导致了上一步入队的不一定是从上一步走过来的,显然不能这么写

3.那怎么办呢,显然普通的vis数组并不能直接判重了,因为同一方格可能经过多次,要么是翻越其他障碍过来的,要么是从空地过来的。大部分人应该都是使用一个三重数组vis[r][c][k]来表示翻过k个障碍到达了点(r,c)。因为每个节点对应某一k有且仅有一条路径,那么这样去判重就可以解决问题了,这个博客写的挺好

4.逛着逛着发现了一个更好用的方法,其实不用设置三维的vis数组判重,我平时写BFS一般是入队后直接设置vis,那么,我们不再这样做,而是改为每次出队后再标记,因为可能会造成把可以穿出障碍的路给标记了

5.这道题思考了近一天,加深了我对BFS的理解,平时我们的BFS是这样去搜索的(以本题样例二为例):

由上图可以看出BFS确实是一层一层搜索。正常来说,每个节点保证只入队判断一次即可,但是由于本题的特殊性,如果是出队时对节点进行标记,代表能从上一层走通到当前节点,那么由于BFS是层序遍历,无论它是怎么到达的我们不必关心,因为最短路径一定相同。那么,图中可以由两条路径到达的节点(如节点(2,2) ),就会入队两次,因为我们入队时保留了翻越障碍的k值,下面还设了结构体。那么入队的两次对应坐标和最短路都相同,但是表示当前连续翻越的节点数不同,该节点数是由前面两条不同路径保存的翻越节点数加一。因此只要能出队,代表前面可以走的路没有问题了,只要考虑下面的即可

如果还不太明白,自行打印每次while循环中出队后对应的编号:

a[u.r][u.c]=2;
for(int i=1;i<=m;i++){for(int j=1;j<=n;j++)printf("%d ",a[i][j]);printf("\n");
}
printf("\n");

6.其实vis数组完全不需要,我们只要将输入数组设置为除了0和1之外的数即可

代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
struct node{int r,c;int cnt;  //连续翻越的障碍数量int d;    //最短路长度node(int x,int y,int s,int t){ r=x,c=y,cnt=s,d=t; }
};int path[4][2]={ {-1,0},{1,0},{0,-1},{0,1} };
int a[30][30];
int m,n,k,ans;  //ans保存答案bool BFS(){queue<node> q;q.push(node(1,1,0,0));  //起点入队while(!q.empty()){node u=q.front();q.pop();a[u.r][u.c]=-1;    //出队后设置为不可再入队/*打印查看数组状态for(int i=1;i<=m;i++){for(int j=1;j<=n;j++)printf("%d ",a[i][j]);printf("\n");}printf("\n");*/if(u.r==m && u.c==n){ ans=u.d; return true; }for(int i=0;i<4;i++){int x=u.r+path[i][0];int y=u.c+path[i][1];if(a[x][y]==-1) continue;if(x<1 || y<1 || x>m || y>n) continue;  //临界条件判断if(a[x][y]==0){           node v(x,y,0,u.d+1);  //如果空地,下一个节点的连续翻越数目都从0开始q.push(v);}else if(a[x][y]==1 && u.cnt+1<=k){  //如果是障碍而且连续翻越数符合条件入队node v(x,y,u.cnt+1,u.d+1);  //如果空地,下一个节点的连续翻越数目在前一个基础上加一q.push(v);}}}return false;
}int main()
{int t;scanf("%d",&t);while(t--){scanf("%d%d%d",&m,&n,&k);for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);if(BFS()) printf("%d\n",ans);else printf("-1\n");}return 0;
}

UVa1600 Patrol Robot (BFS求最短路进阶)相关推荐

  1. *【ZOJ - 3781】Paint the Grid Reloaded(dfs求连通块缩点,bfs求最短路,建图技巧)

    题干: Leo has a grid with N rows and M columns. All cells are painted with either black or white initi ...

  2. UVa 816 (BFS求最短路)

    /*816 - Abbott's Revenge ---代码完全参考刘汝佳算法入门经典 ---strchr() 用来查找某字符在字符串中首次出现的位置,其原型为:char * strchr (cons ...

  3. 算法提高课-图论-单源最短路的建图方式-AcWing 920. 最优乘车:bfs求最短路、建图

    题目分析 来源:acwing 分析: 本题难在抽象建图上,这里采用的建图方式是:同一条公交线路上,前面的站点都可以连一条有向边到其后面的站点,且边权都为1. 由于边权都是1,可以用bfs来求最短路. ...

  4. AcWing 845. 八数码(3阶数字华容道):bfs求最短路,状态表示困难

    文章目录 题目 题目分析 题目 题目链接:AcWing 845. 八数码(数字华容道) 在一个3×3的网格中,1~8这8个数字和一个"x"恰好不重不漏地分布在这3×3的网格中. 例 ...

  5. Codeforces D. Fair 多源BFS求最短路

    点击打开链接 D. Fair time limit per test 2 seconds memory limit per test 512 megabytes input standard inpu ...

  6. 魔戒-BFS求最短路

    魔戒 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 蓝色空间号和万有引力号进入了四维水洼, ...

  7. 2018ACM-ICPC 焦作站现场赛 F. Honeycomb(BFS求最短路,卡memset)

    F. Honeycomb 从前不信命,从这道题开始,我信了. 我就是没有拿牌子的命.这道题或者说这个memset,击碎了我所有对ACM的美好记忆. #include<bits/stdc++.h& ...

  8. Wappo BFS求最短路+路径记录

    点击打开链接 描述 Einstein最近迷上了一款手机益智游戏Wappo,但是由于IQ和RP等诸多原因,他一直无法通关,他希望你编一个程序来玩这个游戏. Wappo的游戏规则是这样的:在一张m*n的地 ...

  9. CSP认证201703-4 地铁修建[C++题解]:连通路径上的最大边权最小、bfs求边权为1的最短路、二分查找

    文章目录 题目解答 题目链接 题目解答 来源:acwing 分析: 题目给定n个点和m条边,要求最多选择n条边,使得1到n连通,然后每段路同时开工,求最小工时.换句话说,求的是连通路上最大边权最小. ...

最新文章

  1. JavaWeb——jsp-config
  2. 为什么阿里巴巴开发手册中强制要求 POJO 类使用包装类型?NPE问题防范
  3. 浅谈MVC设计模式和SSH框架的关系
  4. insert ... on duplicate key update产生death lock死锁原理
  5. 【51Nod - 1182】完美字符串(贪心,字符串)
  6. java向kafka推送数据_Java编写程序将数据存入Kafka中
  7. react中父子组件数据传递,子组件之间的数据传递
  8. struts2 上传文件 HTTP Status 404 - No result defined for action.....and result input
  9. python项目练手(一)------飞船大战游戏
  10. c51为啥要宏定义时钟_C51 程序中 #define 宏定义语句末尾一定要使用分号才能正确编译通过。_学小易找答案...
  11. 由祖冲之圆周率洞悉——古中国数学家的计算力真是惊人
  12. python绘制散点图运行结果是_用python绘制散点图
  13. 离散数学简单复习知识点汇总
  14. 计算机一级vlookup函数的使用方法,Vlookup函数的使用方法 Vlookup函数的操作实例...
  15. 【数据分析】——分析方法
  16. The Chicken and the Pig
  17. 2022年国家高新技术企业认定最新变化
  18. 详细介绍js函数中的arguments
  19. 联发科希望P40和P70救命,能如愿么?
  20. linux dbg,linux下dbg

热门文章

  1. Witt向量简介 §4.1:关于组合数是整数的一种严格证明
  2. CSS 文字内容底部对齐
  3. USB host、usb device、USB OTG的判断
  4. 核心板在麻醉系统中的应用
  5. centos6.4下安装fetion
  6. 蓝桥杯:旅行家的预算 贪心解法
  7. matlab图像处理学习——matlab图形可视化
  8. JavaScript-事件高级
  9. 甘肃环县村民迁新居不弃良田 建“自乐班”融洽村邻
  10. 服务器生成镜像文件,云服务器 生成镜像