[编程题]推箱子

题目来源:牛客网

[编程题] 推箱子
大家一定玩过“推箱子”这个经典的游戏。具体规则就是在一个N*M的地图上,有1个玩家、1个箱子、1个目的地以及若干障碍,其余是空地。玩家可以往上下左右4个方向移动,但是不能移动出地图或者移动到障碍里去。如果往这个方向移动推到了箱子,箱子也会按这个方向移动一格,当然,箱子也不能被推出地图或推到障碍里。当箱子被推到目的地以后,游戏目标达成。现在告诉你游戏开始是初始的地图布局,请你求出玩家最少需要移动多少步才能够将游戏目标达成。
输入描述:
每个测试输入包含1个测试用例
第一行输入两个数字N,M表示地图的大小。其中0<N,M<=8。
接下来有N行,每行包含M个字符表示该行地图。其中 .表示空地、X表示玩家、*表示箱子、#表示障碍、@表示目的地。
每个地图必定包含1个玩家、1个箱子、1个目的地。

输出描述:
输出一个数字表示玩家最少需要移动多少步才能将游戏目标达成。当无论如何达成不了的时候,输出-1。

输入例子:

4 4
....
..*@
....
.X..
6 6
...#..
......
#*##..
..##.#
..X...
.@#...

输出例子:
3
11
*/

主要方法是dfs,

本代码中移动位置时以人的位置为参考,人分别上下左右移动,判断新位置是否可达–>(如果可达)移动是否影响到箱子–>(如果影响到箱子)箱子的新位置是否可达。

也可以以箱子的位置为参考,分别上下左右移动,判断新位置是否可达–>(如果可达)反方向处人是否可达,同时记录人的移动步数。


#include <iostream>
#include <queue>

using namespace std;

struct pt
{
    int x;
    int y;
};

struct pos
{
    pt ppos;
    pt bpos;
};

bool map[8][8];
int status[8][8][8][8];
pt dst, person, box;
int minlength;

void dfs(int row, int col)
{
    for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++)
    for (int m = 0; m < 8; m++)
    for (int n = 0; n < 8; n++)
    {
        status[i][j][m][n] = -1;
    }
    status[person.x][person.y][box.x][box.y] = 0;
    queue<pos>slist;
    pos start = { person, box };
    slist.push(start);
    while (!slist.empty())
    {
        pos cur = slist.front();
        slist.pop();
        int px = cur.ppos.x;
        int py = cur.ppos.y;
        int bx = cur.bpos.x;
        int by = cur.bpos.y;
        int len = status[px][py][bx][by];
        if (bx == dst.x && by == dst.y)
        {
            minlength = len;
            return;
        }
        else
        {
            //上
            if ((px - 1) >= 0 && map[px - 1][py])
            {
                pt ppos = { px - 1, py };
                if ((px - 1) == bx && py == by)
                {
                    if ((bx - 1) >= 0 && map[bx - 1][by] && status[px - 1][py][bx - 1][by] == -1)
                    {
                        status[px - 1][py][bx - 1][by] = len + 1;
                        pt bpos = { bx - 1, by };
                        pos newpos = { ppos, bpos };
                        slist.push(newpos);
                    }
                }
                else if (status[px - 1][py][bx][by] == -1)
                {
                    status[px - 1][py][bx][by] = len + 1;
                    pos newpos = { ppos, cur.bpos };
                    slist.push(newpos);
                }
            }
            //下
            if ((px + 1) < row && map[px + 1][py])
            {
                pt ppos = { px + 1, py };
                if ((px + 1) == bx && py == by)
                {
                    if ((bx + 1) < row  && map[bx + 1][by] && status[px + 1][py][bx + 1][by] == -1)
                    {
                        status[px + 1][py][bx + 1][by] = len + 1;
                        pt bpos = { bx + 1, by };
                        pos newpos = { ppos, bpos };
                        slist.push(newpos);
                    }
                }
                else if (status[px + 1][py][bx][by] == -1)
                {
                    status[px + 1][py][bx][by] = len + 1;
                    pos newpos = { ppos, cur.bpos };
                    slist.push(newpos);
                }
            }
            //左
            if ((py - 1) >= 0 && map[px][py - 1])
            {
                pt ppos = { px, py - 1 };
                if (px == bx && (py - 1) == by)
                {
                    if ((by - 1) >= 0 && map[bx][by - 1] && status[px][py - 1][bx][by - 1] == -1)
                    {
                        status[px][py - 1][bx][by - 1] = len + 1;
                        pt bpos = { bx, by - 1 };
                        pos newpos = { ppos, bpos };
                        slist.push(newpos);
                    }
                }
                else if (status[px][py - 1][bx][by] == -1)
                {
                    status[px][py - 1][bx][by] = len + 1;
                    pos newpos = { ppos, cur.bpos };
                    slist.push(newpos);
                }
            }
            //右
            if ((py + 1) < col && map[px][py + 1])
            {
                pt ppos = { px, py + 1 };
                if (px == bx && (py + 1) == by)
                {
                    if ((by + 1) < col && map[bx][by + 1] && status[px][py + 1][bx][by + 1] == -1)
                    {
                        status[px][py + 1][bx][by + 1] = len + 1;
                        pt bpos = { bx, by + 1 };
                        pos newpos = { ppos, bpos };
                        slist.push(newpos);
                    }
                }
                else if (status[px][py + 1][bx][by] == -1)
                {
                    status[px][py + 1][bx][by] = len + 1;
                    pos newpos = { ppos, cur.bpos };
                    slist.push(newpos);
                }
            }
        }
    }
    minlength = -1;
}

int main(void)
{
    int row, col;
    cin >> row >> col;

    for (int i = 0; i < row; i++)
    for (int j = 0; j < col; j++)
    {
        char a;
        cin >> a;
        do
        {
            cin >> a;
        } while (a == ' ');
        switch (a)
        {
        case '.':map[i][j] = true; break;
        case 'X':
            map[i][j] = true;
            person.x = i; person.y = j;
            break;
        case '*':
            map[i][j] = true;
            box.x = i; box.y = j;
            break;
        case '#':
            map[i][j] = false;
            break;
        case '@':
            map[i][j] = true;
            dst.x = i; dst.y = j;
            break;
        }
    }
    //输入完毕,开始搜索
    dfs(row, col);
    cout << minlength;
    cin.get();
    cin.get();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值