题目来源


题意:

给出 N*N 的棋盘,每个位置可能有障碍物。
行走规则:

  • 每步操作可以往斜着的四个方向走任意格。
  • 如果从 (x1, y1) 走到 (x2, y2),需要保证这条路径中没有障碍物。

一个棋子从起点 (sx, sy) 出发,问最少走多少步能够到达终点 (ex, ey) ?


思路:

很明显能够看出来是 bfs 中的洪水填充问题。

对于每个方向,将这个方向中的能走的所有点都放进队列。

对于每个点,先遍历四个方向,再遍历这个方向中的所有点:

  • 走到一个点,如果之前走过了,跳过。
  • 如果走到障碍物了,那么该方向上障碍物后面的点都不能走,break。

每个点第一个到达所走的步数就是到该点的最少步数。

但是,在这个题中,这样写很大几率会 T。
所以需要用一点记忆化

注意到,如果之前按照方向 dir 走过一个点 x,那么该方向上其后面的所有点都应该走过了。
那么如果后面再按照这个方向遇到这个点时,虽然跳过了,其后面的所有点虽然不会更新,但还是会遍历一遍。其实没有必要遍历的。

所以可以用一个三维数组来标记每个点是否被走过,是从哪个方向走过的。

  • 如果发现当前点走过了,并且是按当前的方向走过的,那么后面的所有点就没必要遍历了,直接break。
  • 如果发现当前点没走过,那么把该方向标记为1,更新该点。
  • 还有需要注意的是,如果当前点走过,但不是当前的方向,先别急着continue。因为接下来会遍历该方向上后面的所有点,那么也就是该点的这个方向也走过了,将这个方向标记为1。

这样,每个点最多被走四次,复杂度很低~

#include<bits/stdc++.h>
using namespace std;#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define mem(a,b) memset(a,b,sizeof a)
#define int long long
#define PII pair<int,int>
#define pb push_back
#define fi first
#define se second
#define endl '\n'
//map<int,int> mp;const int N = 2010, mod = 1e9+7;
int T, n, m;
int a[N][N];
int stx, sty, enx, eny;
int f[N][N], mp[N][N][4];
int dir[4][2] = {{1, 1}, {1, -1}, {-1, 1}, {-1, -1}};void bfs()
{queue<PII> que;que.push({stx, sty});f[stx][sty] = 1;while(que.size()){int x = que.front().fi, y = que.front().se;que.pop();for(int i=0;i<4;i++){for(int d=1;;d++){int tx = x + d*dir[i][0], ty = y + d*dir[i][1];if(tx < 1 || ty < 1 || tx > n || ty > n) break;if(a[tx][ty]) break;if(mp[tx][ty][i]) break;else if(f[tx][ty]){mp[tx][ty][i] = 1;continue;}f[tx][ty] = f[x][y] + 1;mp[tx][ty][i] = 1;que.push({tx, ty});if(tx == enx && ty == eny) return;}}}
}signed main(){Ios;cin>>n;cin>>stx>>sty>>enx>>eny;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){char c;cin>>c;if(c=='#') a[i][j] = 1;}}bfs();cout << f[enx][eny]-1;return 0;
}

这样记忆化之后,6s 的时限 300多ms 就跑完了~

ABC 246: E - Bishop 2——Flood Fill + 记忆化方向相关推荐

  1. LeetCode Number of Islands(flood fill)

    问题:给出一个由0和1组成的二维网格图(m*n),1表示陆地,0表示水.要求统计有多少块陆地 思路:常见的flood fill算法有三种,深度优先搜索.广度优先搜索以及广度扫描法.广度扫描法其实原理与 ...

  2. flood fill算法

    flood fill算法实现有三种形式 1.depth first search 2.breadth first search 3.breadth first scan 基本思想是找到还没有分配com ...

  3. usaco The Castle(flood fill)

    问题:城堡有n*m个方块组成,方块四周可能有墙,分别用1(W),2(N),4(E),8(S)来表示,每个方块由一个数字来表示,由四周的分布的墙值和来表示.要求求出城堡有多少个房间,最大房间的大小及删除 ...

  4. 算法提高课-搜索-Flood fill算法-AcWing 1106. 山峰和山谷:flood fill、bfs

    题目分析 来源:acwing 分析:这道题还是flood fill算法的应用,不同点在于八个方向扫描,习惯性采用二重循环来扫描周围的8个方向:其次,这里需要统计周围比它高的和比它矮的,这点用bool变 ...

  5. 算法提高课-搜索-Flood fill算法-AcWing 1098. 城堡问题:flood fill、bfs

    题目分析 来源:acwing 分析:找房间个数,也就是找连通的个数. 样例画出来的房间个数如下图:其中'|' 和'-'不是墙,只有#是墙. 分析:这题不用建图,直接bfs(flood fill)来做, ...

  6. 算法提高课-搜索-Flood fill算法-AcWing 1097. 池塘计数:flood fill、bfs

    Flood fill 算法简介: 像洪水一样,一圈一圈往外蔓延,像bfs. flood fill 算法可以在线性复杂度内,找到某个点所在的连通块. 题目分析 来源:acwing ac代码 #inclu ...

  7. C语言flood fill 泛洪算法(附完整源码)

    C语言flood fill 泛洪算法 泛洪算法引出 C语言flood fill 泛洪算法完整源码(定义,实现,main函数测试) 泛洪算法引出 给定2D屏幕,像素的位置和要填充的颜色的新值,请用新颜色 ...

  8. 洪水填充算法_洪水填充(Flood fill)算法

    洪水填充(Flood fill)算法 从一个起始节点开始把附近与其连通的节点提取出或填充成不同颜色颜色,直到封闭区域内的所有节点都被处理过为止,是从一个区域中提取若干个连通的点与其他相邻区域区分开(或 ...

  9. 图像处理------泛洪填充算法(Flood Fill Algorithm) 油漆桶功能

    泛洪填充算法(Flood Fill Algorithm) 泛洪填充算法又称洪水填充算法是在很多图形绘制软件中常用的填充算法,最熟悉不过就是 windows paint的油漆桶功能.算法的原理很简单,就 ...

最新文章

  1. django之Ajax
  2. 【转】ASP中的SQL注入
  3. Coolite TextField添加回车事件
  4. Python - 遍历列表时删除元素的正确做法
  5. Linux下WebLogic 12c启动、部署命令行
  6. 通过判断流的头 判断文件类型
  7. 练习:----计算阶乘按钮
  8. openwrt源码下载
  9. 显示器色域检测软件_摄影师:手机看图的甲方爸爸值得我换专业摄影显示器吗?...
  10. 浏览器处理 前台传递的+时出现问题
  11. 怎样用Java生成随机数?
  12. python样本期望值_总体是指数分布,样本均值倒数的期望和方差如何求?
  13. 网页加速系列(六)、 网页加速之进阶下篇
  14. 英诺重明320T服务器安装VMware操作系统流程(图文超详细版)
  15. 全球机场与航空公司准点率数据报告,为五一小长假做足准备
  16. JAVA学习日志 关于dowhile在周易数字卦程序里的应用
  17. linux进阶-scp命令及相关传输命令全get
  18. aspen压缩因子_ASPEN PLUS的物性数据库及其应用.pdf
  19. 去加拿大跟Bengio读硕vs斯坦福全奖ML博士,选哪个?
  20. ps切图(6)——参考线及辅助

热门文章

  1. 虚拟机Vmware玩游戏运行卡顿还有慢的问题解决办法
  2. 关于Fastadmin后台表格内容的修改
  3. 链表-单向链表的实现
  4. 高利润赚钱行业有哪些?300的利润使人疯狂
  5. VScode如何配置C语言编译环境
  6. 染纱厂车间一个普通员工的工资
  7. 树莓派利用socket传图到pc端(Python)
  8. Matlab绘图案例,MATLAB画图大法,附详细代码
  9. 推荐一款全能的计算器软件
  10. JAVA自学笔记(1)