题目大意

游戏地图是一个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”。
每个结果占一行。

样例

输入样例:
7 7
#######
#..X###
#..##O#
#....E#
#....E#
#.....#
#######
0 0
输出样例:
10

思路
       形如给定一个矩形地图, 控制一个物体在地图中按要求移动,求 “最少步数” 的问题。广度优先搜索很擅长解决这种问题一一地图的整体形态是固定不变的,只有少数个体或特征随着每一步操作发生改变。我们只需要把这些变化的部分提取为状态,把起始状态加入队列,使用广度优先搜索不断取出队头状态,沿着分支扩展、入队即可。广度优先搜索是逐层遍历搜索树的算法,所有状态按照入队的先后顺序具有层次单调性(也就是步数单调性)。如果每一次扩展恰好对应一步,那么当一个状态第一次被访问 (入队)时,就得到了从起始状态到达该状态的最少步数。

在这道题目中,不变的是整个地图,变化的部分有长方体的位置和放置形态。我们可以用一个三元组(x,y,lie) 代表一 个状态(搜索树中的一个节点),其中lie=0表示长方体立在(x,y); lie=1 表示长方体横向躺着,左半部分位置在(x,y): lie=2表示长方体纵向躺着,上半部分在(x,y), 并用数组d[x][v][lie] 记录从起始状态到达每个状态的最少步数。然后执行广度优先搜索即可。为了程序实现方便,我们用数字0~3分别代指左、右、上、下四个方向。

状态 0 立着

状态 1 横着

状态 2 竖着

用数组来表示4个方向 左 右 上 下 运动后 x, y, lie 的变化

int next_x[3][4] = {{0, 0, -2, 1}, {0, 0, -1, 1}, {0, 0, -1, 2}};
int next_y[3][4] = {{-2, 1, 0, 0}, {-1, 2, 0, 0}, {-1, 1, 0, 0}};
int next_lie[3][4] = {{1, 1, 2, 2}, {0, 0, 1, 1}, {2, 2, 0, 0}};

用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];

用get_se()函数得到初始的起点和起点状态,和终点

void get_se(){}

用valid函数判断下一个状态的合法性

//判断点是否越界
bool valid(int x, int y){return x >= 0 && y >= 0 && x < n && y < m;
}
//判断下一个状态是否合理
bool valid(state next){if(!valid(next.x, next.y)) return false;if(s[next.x][next.y] == '#') return false;if(next.lie == 0 && s[next.x][next.y] != '.') return false;if(next.lie == 1 && s[next.x][next.y + 1] == '#') return false;if(next.lie == 2 && s[next.x + 1][next.y] == '#') return false;return true;
}

完整代码

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 510;
struct state{int x, y; //坐标 int lie; // 状态
};
char s[N][N];
state st, ed;
int n, m;
int dis[N][N][3]; //记录最小步数
queue<state> q;
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
bool valid(int x, int y){return x >= 0 && y >= 0 && x < n && y < m;
}
bool valid(state next){if(!valid(next.x, next.y)) return false;if(s[next.x][next.y] == '#') return false;if(next.lie == 0 && s[next.x][next.y] != '.') return false;if(next.lie == 1 && s[next.x][next.y + 1] == '#') return false;if(next.lie == 2 && s[next.x + 1][next.y] == '#') return false;return true;
}
void get_se(){for (int i = 0; i < n ; i++){for(int j = 0; j < m; j++){if(s[i][j] == 'O'){ed.x = i;ed.y = j;ed.lie = 0;s[i][j] = '.';}else if(s[i][j] == 'X'){for(int k = 0; k < 4; k++){int x = i + dx[k];int y = j + dy[k];if(valid(x, y) && s[x][y] == 'X'){st.x = min(i, x);st.y = min(j, y);st.lie = k < 2 ? 1 :2;s[i][j] = s[x][y] = '.';break;}}if(s[i][j] == 'X'){st.x = i;st.y = j;st.lie = 0;}}}}
}
int next_x[3][4] = {{0, 0, -2, 1}, {0, 0, -1, 1}, {0, 0, -1, 2}};
int next_y[3][4] = {{-2, 1, 0, 0}, {-1, 2, 0, 0}, {-1, 1, 0, 0}};
int next_lie[3][4] = {{1, 1, 2, 2}, {0, 0, 1, 1}, {2, 2, 0, 0}};
int bfs(){memset(dis, -1, sizeof dis);while(q.size()) q.pop();dis[st.x][st.y][st.lie] = 0;q.push(st);while(q.size()){state now = q.front();q.pop();for(int i = 0; i < 4; i++){state 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(!valid(next)) continue;if(dis[next.x][next.y][next.lie] == -1){dis[next.x][next.y][next.lie] = dis[now.x][now.y][now.lie] + 1;q.push(next);if(next.x == ed.x && next.y == ed.y && next.lie == ed.lie)return dis[next.x][next.y][next.lie];}}}return -1;
}int main(){while(~scanf("%d%d", &n, &m) && n){for(int i = 0; i < n; i++)scanf("%s", s[i]); get_se();int ans = bfs();if(ans == -1)cout << "Impossible" << endl;else cout << ans << endl;}    return 0;
}

POJ3322 Bloxorz “迷宫”类经典例题相关推荐

  1. c语言 异或_C语言经典例题来袭!5大方法告诉你答案

    各位,今天我们来看一个C语言的经典例题,因为最近有不少人后台问的问题都跟这个或多或少有点关系,所以今天咱们拿出来对这类问题进行一个总结,话不多说,就问下面的代码会输出什么? #include 意图很明 ...

  2. PHP盈亏问题,小升初数学必考经典应用题—盈亏问题!(附经典例题分析)

    这种题目中往往有两种分配方案,每种分配方案的结果会出现多(盈)或少(亏)的情况,通常把这类问题,叫做盈亏问题(也叫做盈不足问题). 解答这类问题时,应该先将两种分配方案进行比较,求出由于每份数的变化所 ...

  3. 复杂电路简化经典例题_【中考物理】电路简化的10大原则和7大步骤

    电路问题是初中物理比较难的知识,也是中考很重要的一部分.很多同学遇到电路类的题目,摆在面前的第一个问题就是不会简化电路图. 今天给大家分享电路简化的10大原则和7大步骤,希望能够帮你解决这个难题! 电 ...

  4. 贪心算法经典例题分析

    贪心经典例题 一.区间覆盖问题 例题:洛谷P1803 这是一个非常简单的区间覆盖问题. 针对此类问题,最佳的贪心算法应为将每一个区间的结束时间从小到大排序. 令所选的第 i 个区间的结束时间为 e[i ...

  5. C++两个函数可以相互递归吗_[算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进

    [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...

  6. [算法系列] 深入递归本质+经典例题解析——如何逐步生成, 以此类推,步步为营

    [算法系列] 深入递归本质+经典例题解析--如何逐步生成, 以此类推,步步为营 本文是递归系列的第三篇, 第一篇介绍了递归的形式以及递归设计方法(迭代改递归),;第二篇以递归为引子, 详细介绍了快排和 ...

  7. 算法学习 (门徒计划)4-1 单调队列及经典问题及经典例题 学习笔记

    算法学习 (门徒计划)4-1 单调队列及经典问题及经典例题 学习笔记 前言 单调队列 场景举例(RMQ) 应用-维护区间最值的方式 数据结构-自行设计单调队列 代码实现(java) 例题分析(略) 总 ...

  8. [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进

    [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...

  9. ヾ(o◕∀◕)ノヾ各种动态规划经典例题(新手向、多类型)

    ヾ(o◕∀◕)ノヾ各种动态规划经典例题(新手向.多类型) 一.前言 ヾ(・ω・`。)我把比较常见的类型的动态规划找了一些经典的例题,适合作为新手的入门例题,用于帮助我们对各种不同的动态规划有所了解,很 ...

最新文章

  1. 关于mysql的ddl_log.log文件
  2. echarts树状图点击展开子节点_CPU眼里的结构设备树节点及属性详解
  3. 【数据结构与算法】广义表的储存结构和结点定义的Java实现
  4. Netty工作笔记0058---Netty群聊系统客户端
  5. 为什么那么多公司不用 .NET,而选择PHP、JSP,是 .NET有什么缺点吗?
  6. 美国网络安全体系架构揭秘
  7. Django REST框架
  8. 产品读书《极简工作法则》
  9. 电子废物回收的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  10. Usb ssh 管理android,Android USB VID PID 及 ADB
  11. 性能服务器e5,英特尔至强E5服务器到底有多强?
  12. 第十八章 Radix树路由表
  13. 【python量化】用时间卷积神经网络(TCN)进行股价预测
  14. 马尔可夫毯(Markov Blanket)
  15. python 扩展c extention
  16. 孢子社群:今日推荐ARVR微信群:游乐VR智能
  17. mysql数据库名词术语_【千寻】MySQL数据库名词注释(持续更新)
  18. 写一个自我简介,列出对软件工程课程的希望及个人目标
  19. 华为C/C++笔试题(附答案,华为面试题系列)
  20. 北京小学几年级学计算机,2019年北京小学入学政策年龄规定及入学条件报名时间...

热门文章

  1. Office 2003轻松安装
  2. 关于flash remotObject
  3. [公告] 2017年9月装机员系统更新
  4. 网吧游戏下载器,免费不限速!
  5. R语言 无敌小抄 cheatsheet
  6. unittest框架知识总结
  7. kaldi-yesno例子
  8. android 百度地图定位总结
  9. s3c6410_地址映射
  10. centos8 安装中文输入法详细教程