只是记录一下自己的学习过程
题目描述
推箱子是一款经典游戏。这里我们玩的是一个简单版本,就是在一个N*M的地图上,有1个玩家、1个箱子、1个目的地以及若干障碍,其余是空地。玩家可以往上下左右4个方向移动,但是不能移动出地图或者移动到障碍里去。如果往这个方向移动推到了箱子,箱子也会按这个方向移动一格,当然,箱子也不能被推出地图或推到障碍里。当箱子被推到目的地以后,游戏目标达成。现在告诉你游戏开始是初始的地图布局,要求用深度优先搜索找到游戏的解(注意这里不保证步数最少)。
玩家每到一个格子,就按上(U),右®,下(D),左(L)顺时针方向尝试,每一个方向都都在前一个方向失败时才可能尝试。如下图,如果s6为终态,则游戏解为UU; 如果s21为终态,则玩家要尝试UU,UR,UD,UL,RU,RR,RD,RL,…,LD, 才能确定LL是游戏的解。
状态由玩家位置和箱子位置构成,算法结构大体如下:
DFS(state s){
for(i = 0; i < 4; i++)
DFS(trans(s, i)); //tans表示状态s往方向i走形成的新状态
}
注意得到解后要立即返回。
输入
第一行输入两个数字N,M表示地图的大小。其中0<N,M<=12。
接下来有N行,每行包含M个字符表示游戏地图。其中 . 表示空地、X表示玩家、*表示箱子、#表示障碍、@表示目的地。
输出
有解时,输出玩家走的每一步。当无论如何达成不了的时候,输出-1。
样例输入
6 6
…#…
…
#*##…
…##.#
…X…
.@#…
样例输出
RRUUULLULDDUURDRRURDDLDDRDLLULLUUDDRRRUUULLULLDRRRLULDDDDRRRUURUULDDDUULLULDDDDRRDRRULLLRRUUULLULDDDD
我的简要分析
这个题目与之前的广度优先版本差不多,不过是使用的探索方法不一样以及需要返回的参数不一样,关于这个问题的分析可以去我的上一篇博客看一下链接。
另外需要注意的是回溯的时候,操作存储是逆序的,所以输出的时候也需要逆序输出。
还有,跟一般的深度探索不一样,若是没有箱子的限制条件,标记位置是否走过的数组在回溯的时候需要清零。但是这个问题,我理解为箱子跟人这样一个位置关系是独立的,所以可以不用清零节约时间,但是起点不能标记,不然回溯之后不好探索其他方向。
强行解释,没有什么道理,懂的大佬可以在评论区解释一下,谢谢。
关于深度优先探索(DFS)推荐这篇博客 链接.
详细代码
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;
char zmap[20][20]; //地图
int jmap[20][20][20][20] = {
0 }; //标记是否走过
int n1, m1; //终点位置
int n2, m2; //起点位置
int n3, m3; //箱子位置
int n, m; //地图大小
int people[4][2] = //人走的位置变化
{
{
-1,0},
{
0,1},
{
1,0},
{
0,-