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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

字节--推箱子

發(fā)布時間:2024/4/11 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字节--推箱子 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

字節(jié)–推箱子

文章目錄

  • 字節(jié)--推箱子
    • 一、題目描述
    • 二、分析
    • 三、代碼

一、題目描述

有一個推箱子的游戲, 一開始的情況如下圖:

上圖中, '.' 表示可到達的位置, '#' 表示不可到達的位置,其中 S 表示你起始的位置, 0表示初始箱子的位置, E表示預(yù)期箱子的位置,你可以走到箱子的上下左右任意一側(cè), 將箱子向另一側(cè)推動。如下圖將箱子向右推動一格;
…S0… -> …S0.

注意不能將箱子推動到'#'上, 也不能將箱子推出邊界;

現(xiàn)在, 給你游戲的初始樣子, 你需要輸出最少幾步能夠完成游戲, 如果不能完成, 則輸出-1。

  • 輸入描述:
第一行為2個數(shù)字,n, m, 表示游戲盤面大小有n 行m 列(5< n, m < 50); 后面為n行字符串,每行字符串有m字符, 表示游戲盤面;
  • 輸出描述:
一個數(shù)字,表示最少幾步能完成游戲,如果不能,輸出-1;輸入例子1: 3 6 .S#..E .#.0.. ......輸出例子1: 11

二、分析

  • 在開始做題前,如果你看到樹、圖的最短路徑你想到了什么?廣搜,對,這道題就是
  • 將人所在位置與箱子所在位置以及所走步數(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; }
  • 另外一種寫法:
#include<algorithm> #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std;const int maxn = 1e3+5; char arr[maxn][maxn]; int n,m; int sx,sy; //人物起始位置 int bx,by; //箱子起始位置 int ex,ey; struct node {int x,y; //當前點坐標int h,d; //當前箱子坐標int step; }; const int maxn_ = 55; int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}}; int vis[maxn_][maxn_][maxn_][maxn_];//1 表示已經(jīng)走過了int bfs(int sx,int sy) {queue<node> q;node f; //f表示隊首f.x = sx;f.y = sy;f.h = bx;f.d = by;f.step = 0;vis[sx][sy][bx][by] = 1; //一開始的狀態(tài)標記為1q.push(f); //將初始狀態(tài)入隊while(!q.empty()) //當隊不空時{f = q.front(); //f接收隊首if(f.h == ex && f.d == ey) //如果隊首坐標為E點坐標,則返回答案{return f.step;}q.pop(); //出隊操作int nstep = f.step + 1; //下一步的步數(shù)為0int nbx = f.h; //表示盒子的橫坐標下一步的盒子假設(shè)還沒移動int nby = f.d; for(int i = 0;i < 4;++i){int nx = f.x + dir[i][0]; //四個方向的某一個方向坐標int ny = f.y + dir[i][1];if(nx < 0 || nx >= n || ny < 0 || ny >= m || arr[nx][ny] == '#') //坐標不合法{continue; //如果出界或者遇到墻,則坐標不合法}if(f.h == ex && f.d == ey){node temp ;temp.x = nx;temp.y = ny;temp.step = f.step + 1;q.push(temp);}if(nx == f.h && ny == f.d) {int ox,oy;ox = nx + dir[i][0]; oy = ny + dir[i][1];if(ox < 0 || ox >= n || oy < 0 || oy >= m || arr[ox][oy] == '#' || arr[ox][oy] == 'X') //坐標不合法{continue;}node temp;temp.x = nx;temp.y = ny;temp.h = ox;temp.d = oy;temp.step = nstep;if(!vis[temp.x][temp.y][temp.h][temp.d]){q.push(temp);}vis[temp.x][temp.y][temp.h][temp.d] = 1;}else if(arr[nx][ny] == '.' || arr[nx][ny] == 'X' || arr[nx][ny] == 'E') //如過遇到的是.和X{node temp;temp.x = nx;temp.y = ny;temp.h = nbx;temp.d = nby;temp.step = nstep;if(!vis[nx][ny][nbx][nby]) //如果狀態(tài)沒遇到過,則入隊{q.push(temp);}vis[temp.x][temp.y][temp.h][temp.d] = 1; //這個狀態(tài)標記為1}}}return -1; }int main() {memset(vis,0,sizeof(vis));while(cin>>n>>m){for(int i = 0;i < n;++i){scanf("%s",arr + i);}for(int i = 0;i < n;++i){for(int j = 0;j < m;++j){if(arr[i][j] == 'S'){sx = i;sy = j; }if(arr[i][j] == '0'){bx = i;by = j;arr[i][j] = '.';}if(arr[i][j] == 'E'){ex = i;ey = j; } }}cout<<bfs(sx,sy)<<endl;}return 0; }

總結(jié)

以上是生活随笔為你收集整理的字节--推箱子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。