立体推箱子是一个风靡世界的小游戏。

游戏地图是一个N行M列的矩阵,每个位置可能是硬地(用”.”表示)、易碎地面(用”E”表示)、禁地(用”#”表示)、起点(用”X”表示)或终点(用”O”表示)。

你的任务是操作一个1×1×2的长方体。

这个长方体在地面上有两种放置形式,“立”在地面上(1×1的面接触地面)或者“躺”在地面上(1×2的面接触地面)。

在每一步操作中,可以按上下左右四个键之一。

按下按键之后,长方体向对应的方向沿着棱滚动90度。

任意时刻,长方体不能有任何部位接触禁地,并且不能立在易碎地面上。

字符”X”标识长方体的起始位置,地图上可能有一个”X”或者两个相邻的”X”。

地图上唯一的一个字符”O”标识目标位置。

求把长方体移动到目标位置(即立在”O”上)所需要的最少步数。

在移动过程中,”X”和”O”标识的位置都可以看作是硬地被利用。

输入格式

输入包含多组测试用例。

对于每个测试用例,第一行包括两个整数N和M。

接下来N行用来描述地图,每行包括M个字符,每个字符表示一块地面的具体状态。

当输入用例N=0,M=0时,表示输入终止,且该用例无需考虑。

输出格式

每个用例输出一个整数表示所需的最少步数,如果无解则输出”Impossible”。

每个结果占一行。

数据范围

3≤N,M≤5003≤N,M≤500

输入样例:

7 7
#######
#..X###
#..##O#
#....E#
#....E#
#.....#
#######
0 0

输出样例:

10

算法:bfs

#include <iostream>
#include <cstdio>
#include <queue> using namespace std; const int maxn = 5e2+; struct rec {
int x, y, lie;
}; int n, m;
char Map[maxn][maxn];
int step[maxn][maxn][]; //存储步数
int dir[][] = {, -, , , -, , , }; //普通方向数组
//设0是立着,1是横着,2是竖着,这三种状态
int next_x[][] = {{, , -, }, {, , -, }, {, , -, }};
int next_y[][] = {{-, , , }, {-, , , }, {-, , , }};
int next_lie[][] = {{, , , }, {, , , }, {, , , }};
struct rec st, ed; //分别是起点和终点位置 bool valid(int x, int y) { //判断是否越界
if(x <= || x > n || y <= || y > m) {
return false;
}
return true;
} void parse_st_ed() { //找起点和终点
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
if(Map[i][j] == 'O') {
ed.x = i;
ed.y = j;
ed.lie = ;
Map[i][j] = '.';
}
if(Map[i][j] == 'X') {
for(int k = ; k < ; k++) {
int dx = dir[k][] + i;
int dy = dir[k][] + j;
if(valid(dx, dy) && Map[dx][dy] == 'X') {
st.x = min(dx, i);
st.y = min(dy, j);
st.lie = k < ? : ; //在dir数组里,0和1是左右,2和3是上下
Map[i][j] = Map[dx][dy] = '.';
break;
}
}
if(Map[i][j] == 'X') {
st.x = i;
st.y = j;
st.lie = ;
Map[i][j] = '.';
}
}
}
}
} bool check(rec next) {
if(!valid(next.x, next.y)) {
return false;
}
if(Map[next.x][next.y] == '#') {
return false;
}
//判断当前位置是否可行
if(next.lie == && Map[next.x][next.y] != '.') {
return false;
}
if(next.lie == && Map[next.x][next.y + ] == '#') {
return false;
}
if(next.lie == && Map[next.x + ][next.y] == '#') {
return false;
}
return true;
} int bfs() {
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
for(int k = ; k < ; k++) {
step[i][j][k] = -;
}
}
}
queue<rec> q;
step[st.x][st.y][st.lie] = ;
q.push(st);
while(!q.empty()) {
rec now = q.front();
q.pop();
for(int i = ; i < ; i++) {
rec next;
next.x = now.x + next_x[now.lie][i];
next.y = now.y + next_y[now.lie][i];
next.lie = next_lie[now.lie][i];
if(check(next) && step[next.x][next.y][next.lie] == -) {
step[next.x][next.y][next.lie] = step[now.x][now.y][now.lie] + ;
q.push(next);
if(next.x == ed.x && next.y == ed.y && next.lie == ed.lie) {
return step[next.x][next.y][next.lie];
}
}
}
}
return -; //无解
} int main() {
while(~scanf("%d %d", &n, &m)) {
if(n == && m == ) {
break;
}
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
cin >> Map[i][j];
}
}
parse_st_ed();
int ans = bfs();
if(ans != -) {
printf("%d\n", ans);
} else {
printf("Impossible\n");
}
} return ;
}

AcWing:172. 立体推箱子(bfs)的更多相关文章

  1. hdu.1254.推箱子(bfs + 优先队列)

    推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  2. HDU 1254 推箱子 BFS

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1254 题目分析: 做这道题,感觉挺简单的,做着做着就错了20次, 我也是醉了, WA到吐的节奏啊! 思 ...

  3. 推箱子 BFS

    [编程题] 推箱子 大家一定玩过“推箱子”这个经典的游戏.具体规则就是在一个N*M的地图上,有1个玩家.1个箱子.1个目的地以及若干障碍,其余是空地.玩家可以往上下左右4个方向移动,但是不能移动出地图 ...

  4. HDU1254:推箱子(bfs+dfs)

    传送门 题意 给出一副图 0.空地1.墙2.箱子3.目的地4.人所在的位置 问最少几步能将箱子推到目的地 分析 这道题难度略大(菜鸡),首先用vis[bx][by][mx][my]记录当箱子(bx,b ...

  5. hdu - 1254 推箱子 (bfs+bfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=1254 题目意思很简单,只要思路对就好. 首先考虑搬运工能否到达推箱子的那个点,这个可以根据箱子前进方向得出搬运工 ...

  6. 推箱子 (hdu1254)(bfs双重广搜)

    推箱子 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission ...

  7. HDU 1254 推箱子(BFS)

    Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不 ...

  8. HDU1254 推箱子(BFS) 2016-07-24 14:24 86人阅读 评论(0) 收藏

    推箱子 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推 ...

  9. hdu 1254 推箱子(双重bfs)

    题目链接 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能 ...

随机推荐

  1. loj 3014「JOI 2019 Final」独特的城市

    loj 我本来是直接口胡了一个意思一样的做法的,但是因为觉得有点假+实现要用并查集(?)就卡了好一会儿... 对于一个点\(x\)来说,独特的点一定在它的最长链上,如果有独特的点不在最长链上,那么最长 ...

  2. Redis-Hash常用命令

    Redis-Hash常用命令 hset key field value 设置一个散列,但是在散列中一次只能设置一个属性,如果要批量设置多个属性,则需要使用 hmset命令 hget key field ...

  3. Linux编译安装GCC

    1. 下载gcc安装包 网址:http://ftp.gnu.org/gnu/gcc/ ,下载对应的安装包,我选择gcc-5.5.0.tar.gz 2. 下载依赖库 一个是mpc,一个是gmp,一个是m ...

  4. DataGrip导出查询结果数据

    1 按钮 2 选择保存位置即可

  5. Linux awk命令 --三剑客老大

    Linux awk命令 --三剑客老大 基本用法: awk  [参数]  ['找谁{干啥}']  文件 参数: -F 分隔符 -v 创建或修改awk变量 OFS 输出分割符 awk显示每一列的时候分隔 ...

  6. python面向编程: 常用模块补充与面向对象

    一.常用模块 1.模块 的用用法 模块的相互导入 绝对导入 从sys.path (项目根目录)开始的完整路径 相对导入 是指相对于当前正在执行的文件开始的路径 只能用于包内模块相互间导入 不能超过顶层 ...

  7. java线程基础巩固---数据同步引入并结合jconsole,jstack以及汇编指令认识synchronized关键字

    对于多线程编程而言其实老生成谈的就是数据同步问题,接下来就会开始接触这块的东东,比较麻烦,但是也是非常重要,所以按部就班的一点点去专研它,下面开始. 数据同步引入: 这里用之前写过的银行叫号的功能做为 ...

  8. Springboot整合Ehcache 解决Mybatis二级缓存数据脏读 -详细

    前面有写了一篇关于这个,但是这几天又改进了一点,就单独一篇在详细说明一下 配置 application.properties ,启用Ehcache # Ehcache缓存 spring.cache.t ...

  9. 将本地代码使用Git上传更新至Github

    注册.配置git 1. 首先注册git image 2.然后下载.配置git 百度“git下载”,然后默认安装,注意的是最后要添加环境变量,最后安装结果如下: image 配置如下: 1.设置本地的s ...

  10. LeetCode 69 x 的平方根

    链接:https://leetcode-cn.com/problems/sqrtx 实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数, ...