推箱子
描述:
绝大多数人都玩过推箱子的游戏,控制一个人将箱子推动到目标位置即获得胜利。现请你编写一个程序,判断将箱子推到目标位置至少需要多少步。
输入:
推箱子的平面区域为固定大小(10*10),使用10行10列输入推箱子的初始局面。其中,0代表空格,1代表墙,2代表箱子,3代表目标位置,4代表人。
注:游戏中只有一个箱子,一个目标位置,一个人。
输出:
输出将箱子推到目标位置的最小步数;若箱子不可能被推到目标位置,输出-1。
输入样例:
0000000000
0000000300
0100000000
0100000000
0101111100
0000010000
0000010000
0020010040
0000010000
0000010000
输出样例:
34
源代码
#include <iostream>
#include <queue>
using namespace std;
int maze[10][10];
int vis[10][10][10][10];
int step[10][10][10][10];
struct Node{
int px, py;
int bx, by;
};
int tx, ty;
int walk[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
void input()
{
int i, j;
char c;
for (i = 0; i < 10;i++)
{
for (j = 0; j < 10; j++)
{
cin >> c;
maze[i][j] = c - '0';
}
}
}
int bfs()
{
int i, j;
queue<Node> q;
Node now, next;
for (i = 0; i < 10;i++)
{
for (j = 0; j < 10;j++)
{
if(maze[i][j] == 4)
{
now.px = i;
now.py = j;
maze[i][j] = 0;
}
if(maze[i][j] == 3)
{
tx = i;
ty = j;
maze[i][j] = 0;
}
if(maze[i][j] == 2)
{
now.bx = i;
now.by = j;
maze[i][j] = 0;
}
}
}
vis[now.px][now.py][now.bx][now.by] = 1;
q.push(now);
while(!q.empty())
{
now = q.front();
q.pop();
for (i = 0; i < 4;i++)
{
next.px = now.px + walk[i][0];
next.py = now.py + walk[i][1];
next.bx = now.bx;
next.by = now.by;
if(next.px < 0 || next.px >= 10 || next.py < 0 || next.py >= 10)//越界
{
continue;
}
else if(vis[next.px][next.py][next.bx][next.by] == 1)//重复
{
continue;
}
else if(maze[next.px][next.py] == 1)//撞墙
{
continue;
}
else if(maze[next.px][next.py] == 0 && (next.px != next.bx || next.py != next.by) )//空格
{
vis[next.px][next.py][next.bx][next.by] = 1;
step[next.px][next.py][next.bx][next.by] = step[now.px][now.py][now.bx][now.by] + 1;
q.push(next);
continue;
}
else//箱子
{
next.bx += walk[i][0];
next.by += walk[i][1];
if(next.bx < 0 || next.bx >= 10 || next.by < 0 || next.by >= 10)//箱子越界
{
continue;
}
if(vis[next.px][next.py][next.bx][next.by] == 1)//重复
{
continue;
}
if(maze[next.bx][next.by] == 1)//撞墙
{
continue;
}
if(maze[next.bx][next.by] == 0)
{
if(next.bx == tx && next.by == ty)
{
return step[now.px][now.py][now.bx][now.by] + 1;
}
vis[next.px][next.py][next.bx][next.by] = 1;
step[next.px][next.py][next.bx][next.by] = step[now.px][now.py][now.bx][now.by] + 1;
q.push(next);
}
}
}
}
return -1;
}
int main()
{
input();
cout << bfs() << endl;
}
思路
还是迷宫的老套路,不过是多了一个箱子:
- 扩展结点非法(撞墙,重复,越界)则continue。
- 扩展结点为空格,就入队并记录。
- 扩展结点为箱子,判断箱子的扩展结点(必须与之前人的扩展结点对应),箱子的扩展结点合法,入队,并记录。
- 箱子到达目标点返回当前步数加1。