推箱子(位元組2018校招Android)
阿新 • • 發佈:2021-02-14
推箱子
題目連結
題目簡介
有一個推箱子的遊戲, 一開始的情況如下圖:
上圖中, ‘.’ 表示可到達的位置, ‘#’ 表示不可到達的位置,其中 S 表示你起始的位置, 0表示初始箱子的位置, E表示預期箱子的位置,你可以走到箱子的上下左右任意一側, 將箱子向另一側推動。如下圖將箱子向右推動一格;
…S0… -> …S0.
注意不能將箱子推動到’#'上, 也不能將箱子推出邊界;
現在, 給你遊戲的初始樣子, 你需要輸出最少幾步能夠完成遊戲, 如果不能完成, 則輸出-1。
解題思路
我一開始看到這道題時感覺難度會比較大,沒有什麼思路,其實不要被題面嚇到了。
- 看到最少需要多少時就會想到用BFS(廣度優先搜尋)
- 然後在搜尋過程中記錄每一步的當前你的位置和箱子的位置,只需要考慮兩個情況
- 你的下一步不是箱子所在的位置,此時只需要更新你的位置
- 你的下一步是箱子所在的位置 ,這個時候如果可以推動箱子的話,需要更新你的位置和箱子的位置
程式碼
#include<bits/stdc++.h>
using namespace std;
int m,n,curx,cury,boxx,boxy,destx,desty;
int mov[4][2] = {1,0,-1,0,0,1,0,-1};
bool vis[50][50][50][50];
char graph[50][50];
struct state{
int curx, cury,boxx,boxy,step;
state(int a,int b,int c,int d,int e):curx(a),cury(b),boxx(c),boxy(d),step(e){}
};
int bfs(){
queue<state>q;
q.push(state(curx,cury,boxx,boxy,0));
vis[curx][cury][boxx][boxy] = 1;
while(!q.empty()){
state cur = q.front();
q.pop();
if (cur.boxx==destx&&cur.boxy==desty)return cur.step;
for(int i=0;i<4;i++){
int new_curx = cur.curx + mov[i][0];
int new_cury = cur.cury + mov[i][1];
if(new_curx<0||new_curx>=n||new_cury<0||new_cury>=m||graph[new_curx][new_cury]=='#')continue;
if(new_curx!=cur.boxx||new_cury!=cur.boxy){
if(vis[new_curx][new_cury][cur.boxx][cur.boxy])continue;
q.push(state(new_curx,new_cury,cur.boxx,cur.boxy,cur.step+1));
vis[new_curx][new_cury][cur.boxx][cur.boxy] = 1;
}else if(new_curx==cur.boxx&&new_cury==cur.boxy){
int new_boxx = cur.boxx+mov[i][0];
int new_boxy = cur.boxy+mov[i][1];
if(new_boxx<0||new_boxx>=n||new_boxy<0||new_boxy>=m||graph[new_boxx][new_boxy]=='#')continue;
if(vis[new_curx][new_cury][new_boxx][new_boxy])continue;
q.push(state(new_curx,new_cury,new_boxx,new_boxy,cur.step+1));
vis[new_curx][new_cury][new_boxx][new_boxy] = 1;
}
}
}
return -1;
}
int main(){
cin >> n >> m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
cin >> graph[i][j];
if(graph[i][j]=='S'){
curx = i;cury = j;
}else if(graph[i][j]=='0'){
boxx = i;boxy = j;
}else if(graph[i][j]=='E'){
destx = i;desty = j;
}
}
cout << bfs() << "\n";
}