栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

2022-5-17 推箱子(未解决)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2022-5-17 推箱子(未解决)

题目

「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置。

游戏地图用大小为 m x n 的网格 grid 表示,其中每个元素可以是墙、地板或者是箱子。

现在你将作为玩家参与游戏,按规则将箱子 'B' 移动到目标位置 'T' :

玩家用字符 'S' 表示,只要他在地板上,就可以在网格中向上、下、左、右四个方向移动。
地板用字符 '.' 表示,意味着可以自由行走。
墙用字符 '#' 表示,意味着障碍物,不能通行。
箱子仅有一个,用字符 'B' 表示。相应地,网格上有一个目标位置 'T'。
玩家需要站在箱子旁边,然后沿着箱子的方向进行移动,此时箱子会被移动到相邻的地板单元格。记作一次「推动」。
玩家无法越过箱子。
返回将箱子推到目标位置的最小 推动 次数,如果无法做到,请返回 -1。

示例
示例 1:
输入:grid = [["#","#","#","#","#","#"],
             ["#","T","#","#","#","#"],
             ["#",".",".","B",".","#"],
             ["#",".","#","#",".","#"],
             ["#",".",".",".","S","#"],
             ["#","#","#","#","#","#"]]
输出:3
解释:我们只需要返回推箱子的次数。
示例 2:
输入:grid = [["#","#","#","#","#","#"],
             ["#","T","#","#","#","#"],
             ["#",".",".","B",".","#"],
             ["#","#","#","#",".","#"],
             ["#",".",".",".","S","#"],
             ["#","#","#","#","#","#"]]
输出:-1
示例 3:
输入:grid = [["#","#","#","#","#","#"],
             ["#","T",".",".","#","#"],
             ["#",".","#","B",".","#"],
             ["#",".",".",".",".","#"],
             ["#",".",".",".","S","#"],
             ["#","#","#","#","#","#"]]
输出:5
解释:向下、向左、向左、向上再向上。
提示
  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 20
  • grid 仅包含字符 '.', '#', 'S' , 'T', 以及 'B'。
  • grid 中 'S', 'B' 和 'T' 各只能出现一个。
代码1 (未解决)

以下示例答案为8,输出结果为INT_MAX,代码待修正。

#include 

#define N 20
#pragma GCC optimize(2)

int xMax, yMax, xTarget, yTarget, minMove;

using namespace std;

const int DIR[4][2]{{-1, 0},
                    {1,  0},
                    {0,  -1},
                    {0,  1}};

bool visited[N][N][4]{false};

bool isObstacle(const vector> &grid, int x, int y) {
    return x < 0 || y < 0 || x >= xMax || y >= yMax || grid[x][y] != '.';
}

bool isAccessible(vector> &grid, int xStart, int yStart, int xEnd, int yEnd) {
    if (isObstacle(grid, xEnd, yEnd)) { return false; }
    if (xStart == xEnd && yStart == yEnd) { return true; }
    for (int i = 0, dx, dy; i < 4; i++) {
        dx = DIR[i][0], dy = DIR[i][1];
        if (!isObstacle(grid, xStart + dx, yStart + dy)) {
            char prev = grid[xStart][yStart];
            grid[xStart][yStart] = 'V';
            if (isAccessible(grid, xStart + dx, yStart + dy, xEnd, yEnd)) {
                grid[xStart][yStart] = prev;
                return true;
            }
            grid[xStart][yStart] = prev;
        }
    }
    return false;
}

tuple convertGrid(vector> &grid) {
    int xHuman, yHuman, xBox, yBox;
    for (int i = 0; i < xMax; i++) {
        for (int j = 0; j < yMax; j++) {
            if (grid[i][j] == 'B') { xBox = i, yBox = j; }
            if (grid[i][j] == 'S') { xHuman = i, yHuman = j, grid[i][j] = '.'; }
            if (grid[i][j] == 'T') { xTarget = i, yTarget = j, grid[i][j] = '.'; }
        }
    }
    return tuple{xHuman, yHuman, xBox, yBox};
}

void bfs(vector> &grid, int nMove, int iBox, int jBox, int iHuman, int jHuman) {
    if (iBox == xTarget && jBox == yTarget) {
        minMove = min(minMove, nMove);
        return;
    }
    for (int i = 0, dx, dy; i < 4; i++) {
        if (visited[iBox][jBox][i]) continue; // 状态已访问
        visited[iBox][jBox][i] = true; // 访问该状态
        dx = DIR[i][0], dy = DIR[i][1];
        if (isObstacle(grid, iBox + dx, jBox + dy)) continue; // 下一位置为障碍点
        if (!isAccessible(grid, iHuman, jHuman, iBox - dx, jBox - dy)) continue; // 推动箱子的位置不可到达
        grid[iBox][jBox] = '.', grid[iBox + dx][jBox + dy] = 'B';
        bfs(grid, nMove + 1, iBox + dx, jBox + dy, iBox - dx, jBox - dy);
        grid[iBox][jBox] = 'B', grid[iBox + dx][jBox + dy] = '.';
    }
}

int main() {
    vector> grid{{'#', '.', '.', '#', 'T', '#', '#', '#', '#'},
                              {'#', '.', '.', '#', '.', '#', '.', '.', '#'},
                              {'#', '.', '.', '#', '.', '#', 'B', '.', '#'},
                              {'#', '.', '.', '.', '.', '.', '.', '.', '#'},
                              {'#', '.', '.', '.', '.', '#', '.', 'S', '#'},
                              {'#', '.', '.', '#', '.', '#', '#', '#', '#'}};
    xMax = grid.size(), yMax = grid[0].size();
    int xHuman, yHuman, xBox, yBox;
    minMove = INT_MAX;
    tie(xHuman, yHuman, xBox, yBox) = convertGrid(grid);
    bfs(grid, 0, xBox, yBox, xHuman, yHuman);
    cout << minMove;
    return 0;
}

代码2 (超时)
#include 

#pragma GCC optimize(2)

using namespace std;

int step[1 << 20];
int n, m;
int dir[4][2]{{0,  1},
              {1,  0},
              {0,  -1},
              {-1, 0}};

bool isValid(const vector> &grid, int x, int y) {
    return x >= 0 && x < m && y >= 0 && y < n && grid[x][y] != '#';
}

int pack(int xStart, int yStart, int xBox, int yBox) {
    return (xStart << 15) | (yStart << 10) | (xBox << 5) | yBox;
}

tuple unPack(int val) {
    return {val >> 15 & 31, val >> 10 & 31, val >> 5 & 31, val & 31};
}


int minPushBox(vector> &grid) {
    m = grid.size(), n = grid[0].size();
    memset(step, -1, sizeof(step));
    int xStart, yStart, xBox, yBox;
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            if (grid[i][j] == 'S') { xStart = i, yStart = j, grid[i][j] = '.'; }
            if (grid[i][j] == 'B') { xBox = i, yBox = j, grid[i][j] = '.'; }
        }
    }
    queue que;
    int packValue = pack(xStart, yStart, xBox, yBox);
    int ans = -1;
    int xStartNext, yStartNext, xBoxNext, yBoxNext, packValueNext;
    step[packValue] = 0;
    que.push(packValue);
    while (!que.empty()) {
        packValue = que.front();
        que.pop();
        tie(xStart, yStart, xBox, yBox) = unPack(packValue);
        if (grid[xBox][yBox] == 'T') {
            if (ans == -1 || step[packValue] < ans) ans = step[packValue];
            continue;
        }
        for (auto &i : dir) {
            xStartNext = xStart + i[0];
            yStartNext = yStart + i[1];
            if (!isValid(grid, xStartNext, yStartNext)) continue;
            if (xStartNext == xBox && yStartNext == yBox) {
                xBoxNext = xBox + i[0];
                yBoxNext = yBox + i[1];
                if (!isValid(grid, xBoxNext, yBoxNext)) continue;
                packValueNext = pack(xStartNext, yStartNext, xBoxNext, yBoxNext);
                if (step[packValueNext] == -1 || step[packValueNext] + 1 < step[packValue]) {
                    step[packValueNext] = step[packValue] + 1;
                    que.push(packValueNext);
                }
            } else {
                packValueNext = pack(xStartNext, yStartNext, xBox, yBox);
                if (step[packValueNext] == -1 || step[packValueNext] < step[packValue]) {
                    step[packValueNext] = step[packValue];
                    que.push(packValueNext);
                }
            }
        }
    }
    return ans;
}


int main() {
    vector> grid{{'.', '.', '#', '.', '.', '.', '.', '#'},
                              {'.', 'B', '.', '.', '.', '.', '.', '#'},
                              {'.', '.', 'S', '.', '.', '.', '.', '.'},
                              {'.', '#', '.', '.', '.', '.', '.', '.'},
                              {'.', '.', '.', '.', '.', '.', '.', '.'},
                              {'.', '.', '.', 'T', '.', '.', '.', '.'},
                              {'.', '.', '.', '.', '.', '.', '.', '#'},
                              {'.', '#', '.', '.', '.', '.', '.', '.'}};
    cout << minPushBox(grid);
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/892567.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号