字节--推箱子
字節(jié)–推箱子
文章目錄
- 字節(jié)--推箱子
- 一、題目描述
- 二、分析
- 三、代碼
一、題目描述
有一個推箱子的游戲, 一開始的情況如下圖:
上圖中, '.' 表示可到達的位置, '#' 表示不可到達的位置,其中 S 表示你起始的位置, 0表示初始箱子的位置, E表示預(yù)期箱子的位置,你可以走到箱子的上下左右任意一側(cè), 將箱子向另一側(cè)推動。如下圖將箱子向右推動一格;
…S0… -> …S0.
注意不能將箱子推動到'#'上, 也不能將箱子推出邊界;
現(xiàn)在, 給你游戲的初始樣子, 你需要輸出最少幾步能夠完成游戲, 如果不能完成, 則輸出-1。
- 輸入描述:
- 輸出描述:
二、分析
- 在開始做題前,如果你看到樹、圖的最短路徑你想到了什么?廣搜,對,這道題就是
- 將人所在位置與箱子所在位置以及所走步數(shù)看作整體,新建節(jié)點Node。
- 首先初始位置入隊,通過移動不斷將還沒有經(jīng)過的下一位置節(jié)點入隊,直至找到箱子之前箱子的位置是不變的;
- 當人找到箱子之后(即在箱子的一側(cè),上下左右),開始推箱子往另一側(cè)走(下上右左),此時人和箱子的位置都開始移動,直至走到終點或無路可走結(jié)束。
- 解決這道題分為兩步
- ① 人在找到箱子之前單獨移動,箱子原地不動;在這個過程中,人要從“S”走到箱子“0”的旁邊(上下左右)。
- ② 人找到箱子之后和箱子一起向“另一側(cè)”移動,..S0.. -> ...S0. 。
三、代碼
#include <bits/stdc++.h> using namespace std;const int N = 55; //用來標記是否已經(jīng)訪問過 bool vis[N][N][N][N]; // vis[a][b][c][d] 表示人在 (a,b)處,//游戲的初始數(shù)據(jù) char maze[N][N];//棋盤的行、列 //人的起始行、列 //箱子的起始行、列 //目標位置的行、列 int n,m,px,py,boxx,boxy,ex,ey;//把任務(wù)的坐標、箱子的坐標、當前移動的次數(shù)封裝在一起 struct Node {int px,py,boxx,boxy,step;// 重載, step大的Node優(yōu)先級小,在構(gòu)建優(yōu)先級隊列時使用bool operator < (const Node& rs) const{ return rs.step < step;} }s;//控制4個方向 int dir[][2] = {1,0,-1,0,0,1,0,-1};//判斷是否滿足條件 bool judge(int x,int y) {if(x < 0 || x >= n || y < 0 || y >= m || maze[x][y] == '#') return false;return true; }//廣搜 int bfs() {//初始節(jié)點s = {px,py,boxx,boxy,0};//優(yōu)先級隊列priority_queue<Node> q;q.push(s);//進行標記vis[px][py][boxx][boxy] = 1;while(!q.empty()){Node u = q.top();q.pop();//如果箱子到達目標地點,返回移動的次數(shù)if(u.boxx ==ex && u.boxy == ey) return u.step;//枚舉上下左右4個方向for(int i=0;i<4;i++){int pxx = u.px + dir[i][0];int pyy = u.py + dir[i][1]; // 人往該方向走了一步//判斷任務(wù)是否移動到箱子的周圍int boxx = u.boxx,boxy = u.boxy;if(pxx == boxx && pyy == boxy) { // 碰到了箱子則將箱子向外推動一格boxx += dir[i][0];boxy += dir[i][1];}//判斷任務(wù)位置和箱子的位置是否滿足條件if(!judge(pxx,pyy) || !judge(boxx,boxy)) continue;//判斷是否已經(jīng)訪問過if(vis[pxx][pyy][boxx][boxy]) continue;vis[pxx][pyy][boxx][boxy] = 1;q.push({pxx,pyy,boxx,boxy,u.step + 1});}}return -1; }int main() {scanf("%d%d",&n,&m);for(int i = 0;i < n;i++){scanf("%s",maze[i]);for(int j = 0;j < m;j++){//記錄相關(guān)坐標信息if(maze[i][j] == '0')boxx = i,boxy = j,maze[i][j]='.';if(maze[i][j]=='S') px = i,py = j,maze[i][j]='.';if(maze[i][j]=='E') ex = i,ey = j,maze[i][j]='.';}}printf("%d\n",bfs());return 0; }- 另外一種寫法:
總結(jié)