日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2024/7/5 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode 1263. 推箱子(BFS+DFS / 自定义哈希set) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 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)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。