文章目录

  • 1. 题目
  • 2. 解题
    • 2.1 超时解
    • 2.2 BFS + DFS

1. 题目

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

游戏地图用大小为 n * m 的网格 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
解释:向下、向左、向左、向上再向上。示例 4:
输入:grid = [["#","#","#","#","#","#","#"],["#","S","#",".","B","T","#"],["#","#","#","#","#","#","#"]]
输出:-1提示:
1 <= grid.length <= 20
1 <= grid[i].length <= 20
grid 仅包含字符 '.', '#',  'S' , 'T', 以及 'B'。
grid 中 'S', 'B' 和 'T' 各只能出现一个。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-moves-to-move-a-box-to-their-target-location
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

2.1 超时解

15 / 18 个通过测试用例

  • 优先队列里存入 box 和 人的4个坐标位置,以及推的次数,推的次数小的优先
  • 队列里存了太多的状态
class node
{public:int push, bi, bj, pi, pj;node(int n, int a, int b, int c, int d){push = n;bi = a;bj = b;pi = c;pj = d;}
};
struct hashf // 自定义哈希
{unsigned long long operator()(node v) const{return 1ULL*v.push*pow(21,4)+v.bi*pow(21,3)+v.bj*pow(21,2)+v.pi*21+v.pj;}
};
struct eqf // 哈希set 相等判断函数
{bool operator()(node v1, node v2) const//不能写引用,会报错{return v1.push==v2.push && v1.bi==v2.bi && v1.bj==v2.bj&& v1.pi==v2.pi && v1.pj==v2.pj;}
};
struct cmp
{bool operator()(node& a, node& b) const{return a.push > b.push;//推得次数少的优先}
};
class Solution {public:int minPushBox(vector<vector<char>>& grid) {int m = grid.size(), n = grid[0].size(), k = 21;int targetx, targety, boxi, boxj, peoplei, peoplej, push = 0, size;for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(grid[i][j] == 'S')peoplei = i, peoplej = j;else if(grid[i][j] == 'B')boxi = i, boxj = j;else if(grid[i][j] == 'T')targetx = i, targety = j;}}vector<vector<int>> dir = {{1,0},{0,1},{0,-1},{-1,0}};priority_queue<node, vector<node>, cmp> q; node state(0, boxi, boxj, peoplei, peoplej);q.push(state);unordered_set<node, hashf, eqf> vis;vis.insert(state);while(!q.empty()){int pj = q.top().pj;int pi = q.top().pi;int bj = q.top().bj;int bi = q.top().bi;push = q.top().push;if(bi==targetx && bj==targety)return push;q.pop();int nextbi, nextbj, nextpi, nextpj;for(int d = 0; d < 4; d++){nextpi = pi+dir[d][0];nextpj = pj+dir[d][1];state.push = push;if(nextpi==bi && nextpj==bj){ // 推动箱子了nextbi = bi+dir[d][0];nextbj = bj+dir[d][1];state.push++;}else{nextbi = bi;nextbj = bj;}state.bi = nextbi;state.bj = nextbj;state.pi = nextpi;state.pj = nextpj;if(nextpi>=0 && nextpi<m && nextpj>=0 && nextpj<n &&nextbi>=0 && nextbi<m && nextbj>=0 && nextbj<n &&grid[nextpi][nextpj] != '#' && grid[nextbi][nextbj] != '#' &&vis.find(state) == vis.end()){vis.insert(state);q.push(state);}}}return -1;}
};

2.2 BFS + DFS

  • 队列里面只存能推动箱子的状态
  • 中间到达推箱子的过程,不必记录到队列内,采用DFS判断人的位置能否到达推动箱子的位置
  • 不采用优先队列也可以
class node
{public:int push, bi, bj, pi, pj;node(int n, int a, int b, int c, int d){push = n;bi = a;bj = b;pi = c;pj = d;}
};
struct hashf
{unsigned long long operator()(node v) const{return 1ULL*v.bi*pow(21,3)+v.bj*pow(21,2)+v.pi*21+v.pj;}
};
struct eqf
{bool operator()(node v1, node v2) const//不能写引用{return v1.bi==v2.bi && v1.bj==v2.bj&& v1.pi==v2.pi && v1.pj==v2.pj;//2个物品的位置都相等即set中出现过了}
};
struct cmp
{bool operator()(node& a, node& b) const{return a.push > b.push;//推得次数少的优先}
};
class Solution {vector<vector<int>> dir = {{1,0},{0,1},{0,-1},{-1,0}};
public:int minPushBox(vector<vector<char>>& grid) {int m = grid.size(), n = grid[0].size();int targetx, targety, boxi, boxj, peoplei, peoplej, push = 0, size;for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(grid[i][j] == 'S')peoplei = i, peoplej = j;else if(grid[i][j] == 'B')boxi = i, boxj = j;else if(grid[i][j] == 'T')targetx = i, targety = j;}}priority_queue<node, vector<node>, cmp> q; node state(0, boxi, boxj, peoplei, peoplej);q.push(state);unordered_set<node, hashf, eqf> vis;vis.insert(state);while(!q.empty()){int pj = q.top().pj;int pi = q.top().pi;int bj = q.top().bj;int bi = q.top().bi;push = q.top().push;if(bi==targetx && bj==targety)return push;q.pop();int nextbi, nextbj, nextpi, nextpj, pushPosx, pushPosy;for(int d = 0; d < 4; d++){nextbi = bi+dir[d][0];nextbj = bj+dir[d][1];if(nextbi<0 || nextbi>=m || nextbj<0 || nextbj>=n || grid[nextbi][nextbj] == '#')continue; // 箱子下一个位置不合法nextpi = bi;nextpj = bj;pushPosx = bi-dir[d][0];//人推动箱子前的位置pushPosy = bj-dir[d][1];if(pushPosx<0 || pushPosx>=m || pushPosy<0 || pushPosy>=n || grid[pushPosx][pushPosy] == '#')continue; // 推箱子位置不合法vector<vector<bool>> record(m, vector<bool>(n, false));if(!canReachPushPos(grid,pi,pj,bi,bj,pushPosx,pushPosy,record))continue;//不能从当前位置到达推箱子位置state.push = push+1;state.bi = nextbi;state.bj = nextbj;state.pi = nextpi;state.pj = nextpj;if(vis.find(state) == vis.end()){vis.insert(state);q.push(state);}}}return -1;}bool canReachPushPos(vector<vector<char>>& grid, int x0, int y0, int bi, int bj, int tx, int ty, vector<vector<bool>>& vis){vis[x0][y0] = true;if(x0==tx && y0==ty) return true;int m = grid.size(), n = grid[0].size();for(int k = 0; k < 4; k++){int nx = x0+dir[k][0];int ny = y0+dir[k][1];if(nx>=0 && nx<m && ny>=0 && ny<n && grid[nx][ny] != '#' && !(nx==bi && ny==bj) && !vis[nx][ny]){   // box 也不能穿过if(canReachPushPos(grid,nx, ny,bi,bj,tx,ty, vis))return true;}}return false;}
};

240 ms 20.4 MB C++


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!

LeetCode 1263. 推箱子(BFS+DFS / 自定义哈希set)相关推荐

  1. 【LeetCode困难】1263. 推箱子

    「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置. 游戏地图用大小为 m x n 的网格 grid 表示,其中每个元素可以是墙.地板或者是箱子. 现在你将作为玩家参与游戏,按规 ...

  2. hdu.1254.推箱子(bfs + 优先队列)

    推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  3. LeetCode 490. 迷宫(BFS/DFS)

    文章目录 1. 题目 2. 解题 2.1 BFS 2.2 DFS 1. 题目 由空地和墙组成的迷宫中有一个球. 球可以向上下左右四个方向滚动,但在遇到墙壁前不会停止滚动. 当球停下时,可以选择下一个方 ...

  4. HDU 1254 推箱子 BFS

    囧,一开始没有管人的情况,只看箱子,果然SB了. #include <cstdio> #include <cstring> #include <iostream> ...

  5. tzc 1345 推箱子

    http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&contestId=156&id=1345 ...

  6. Leetcode 1263:推箱子(超详细的解法!!!)

    「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置. 游戏地图用大小为 n * m 的网格 grid 表示,其中每个元素可以是墙.地板或者是箱子. 现在你将作为玩家参与游戏,按规 ...

  7. hdu 1254 推箱子(嵌套搜索,bfs中有dfs)

    推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submis ...

  8. javafx 推箱子小游戏object类_突破LeetCode Hard模式之《推箱子》

    导读:算法哥好久没分享有趣的算法题了,有点寂寞空虚冷,今天看到一道似曾相识的题目,而且难度是hard模式,勾起了算法哥的征服欲.特分享之! 题目描述 「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱 ...

  9. 【HDU - 1254 】推箱子 (双bfs)

    题干: 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个 ...

最新文章

  1. Heartbeat V2.x双机热备安装
  2. 模块化加载_前端模块化简单总结
  3. C++设计模式之桥接模式
  4. HOJ 1015 Nearly prime numbers
  5. 如何从一个 C# 的 dump 中挖到机器相关的信息?
  6. 2014全国计算机二级ms office,2014计算机二级MS Office真题及答案
  7. 使用多线程拷贝文件夹
  8. 无光驱不支持USB设备启动的笔记本,如何使用Ghost来安装系统
  9. 【boost】time.1 同步计数器
  10. ASP.NET 2.0运行原理及其过程简要分析
  11. 按键精灵 android,按键精灵手机版
  12. 归并排序java示例
  13. ISO 27001信息安全管理体系认证
  14. U盘必备的5个软件(让你的U盘无所不能)
  15. 51学习记录基于51单片机的简单音乐盒
  16. 3DMAx:能导入导出的文件格式
  17. JQuery实现灯箱特效
  18. Web报表系统葡萄城报表:报表设计
  19. 母亲大人辛苦了(snowfall.jquery实现爱心掉落)
  20. RuntimeError: NEOS requires a valid email address. Please set the ‘NEOS_EMAIL‘ environment variable.

热门文章

  1. python爬取网易云歌单_详解python selenium 爬取网易云音乐歌单名
  2. MySQL5.7升级到8.0 之后,配合ubantu18.04遇到的常规问题以及非常规问题的解决方案
  3. 深入浅出学java_《深入浅出学JAVA开发初级》
  4. 非法操作 login.php,阅文游戏中心 h5游戏接入wiki
  5. 如何把图片嵌到html中,自给自足,轻松将图片图片内嵌到HTML
  6. IDEA将项目打包为指定class文件的jar
  7. jmeter强大的扩展插件!!
  8. 《C++标准程序库》学习笔记5 — 第七章
  9. shell--基本语法
  10. Redis入门指南(第2版) Redis设计思路学习与总结