程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDOJ 1254 推箱子 (BFS)

HDOJ 1254 推箱子 (BFS)

編輯:C++入門知識

 題意:推箱子游戲,在一個M*N的房間裡有一個箱子和一個搬運工,搬運工的工作就是把箱子推到指定的位置,求最少的推箱子的次數,如果不能完成則輸出-1。

思路:帶嵌套的BFS~第一層BFS箱子,箱子每次移動前要再BFS一下人,看人能不能走到推動箱子的位置。

注意://因為人的位置不同時箱子可能可以到同一個位置兩次,所以開4維(兩維是箱子位置,兩維是人的位置)數組標記。


[cpp]
#include<cstdio>  
#include<cstring>  
#include<queue>  
  
using namespace std; 
  
struct node{ 
    int x,y,cnt; 
    int px,py; 
}now,tmp,pnow,ptmp; 
  
queue<struct node>q;//BFS箱子的隊列  
queue<struct node>p;//BFS人的隊列  
  
int m,n; 
int maze[11][11]; 
bool vis[11][11][11][11]; 
bool pvis[11][11]; 
  
int dx[]={0,0,1,-1}; 
int dy[]={1,-1,0,0}; 
  
bool p_ok() 

    if(ptmp.x>=0&&ptmp.y>=0&&ptmp.x<m&&ptmp.y<n&&maze[ptmp.x][ptmp.y]!=1&&!(ptmp.x==now.x&&ptmp.y==now.y)&&!pvis[ptmp.x][ptmp.y]) 
        return true; 
    else 
        return false; 

  
bool p_bfs(int k)//簡單的BFS,i為箱子要去的方向  

    while(!p.empty()) 
        p.pop(); 
    memset(pvis,false,sizeof(pvis)); 
    pnow.x=tmp.px;pnow.y=tmp.py; 
    if(pnow.x==now.x-dx[k]&&pnow.y==now.y-dy[k])//特殊判斷人就在箱子邊上且正好是要推箱子的位置的情況  
        return true; 
    pvis[pnow.x][pnow.y]=true; 
    p.push(pnow); 
    while(!p.empty()) 
    { 
        pnow=p.front(); 
        p.pop(); 
        for(int i=0;i<4;i++) 
        { 
            ptmp=pnow; 
            ptmp.x+=dx[i]; 
            ptmp.y+=dy[i]; 
            if(p_ok()) 
            { 
                if(ptmp.x==now.x-dx[k]&&ptmp.y==now.y-dy[k]) 
                    return true; 
                pvis[ptmp.x][ptmp.y]=true; 
                p.push(ptmp); 
            } 
        } 
    } 
    return false; 

  
bool ok() 

    if(tmp.x>=0&&tmp.y>=0&&tmp.x<m&&tmp.y<n&&maze[tmp.x][tmp.y]!=1&&!vis[tmp.x][tmp.y][tmp.px][tmp.py]) 
        return true; 
    else 
        return false; 

  
int bfs() 

    while(!q.empty()) 
        q.pop(); 
    now.cnt=0; 
    vis[now.x][now.y][now.px][now.py]=true; 
    q.push(now); 
    while(!q.empty()) 
    { 
        now=q.front(); 
        q.pop(); 
        for(int i=0;i<4;i++) 
        { 
            tmp=now; 
            tmp.x+=dx[i]; 
            tmp.y+=dy[i]; 
            if(ok()) 
            { 
                if(p_bfs(i))//判斷人能否走到要推箱子的位置  
                { 
                    tmp.cnt++; 
                    if(maze[tmp.x][tmp.y]==3) 
                        return tmp.cnt; 
                    tmp.px=now.x;tmp.py=now.y; 
                    vis[tmp.x][tmp.y][now.px][now.py]=true; 
                    q.push(tmp); 
                } 
            } 
        } 
    } 
    return -1; 

  
int main() 

    int t; 
    while(scanf("%d",&t)==1) 
    { 
        while(t--) 
        { 
            memset(vis,false,sizeof(vis)); 
            scanf("%d %d",&m,&n); 
            for(int i=0;i<m;i++) 
            { 
                for(int j=0;j<n;j++) 
                { 
                    scanf("%d",&maze[i][j]); 
                    if(maze[i][j]==2){now.x=i;now.y=j;} 
                    else if(maze[i][j]==4){now.px=i;now.py=j;}//初始化BFS箱子的第一個節點  
                } 
            } 
            printf("%d\n",bfs()); 
        } 
    } 
    return 0; 

#include<cstdio>
#include<cstring>
#include<queue>
 
using namespace std;
 
struct node{
 int x,y,cnt;
 int px,py;
}now,tmp,pnow,ptmp;
 
queue<struct node>q;//BFS箱子的隊列
queue<struct node>p;//BFS人的隊列
 
int m,n;
int maze[11][11];
bool vis[11][11][11][11];
bool pvis[11][11];
 
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
 
bool p_ok()
{
 if(ptmp.x>=0&&ptmp.y>=0&&ptmp.x<m&&ptmp.y<n&&maze[ptmp.x][ptmp.y]!=1&&!(ptmp.x==now.x&&ptmp.y==now.y)&&!pvis[ptmp.x][ptmp.y])
  return true;
 else
  return false;
}
 
bool p_bfs(int k)//簡單的BFS,i為箱子要去的方向
{
 while(!p.empty())
  p.pop();
 memset(pvis,false,sizeof(pvis));
 pnow.x=tmp.px;pnow.y=tmp.py;
 if(pnow.x==now.x-dx[k]&&pnow.y==now.y-dy[k])//特殊判斷人就在箱子邊上且正好是要推箱子的位置的情況
  return true;
 pvis[pnow.x][pnow.y]=true;
 p.push(pnow);
 while(!p.empty())
 {
  pnow=p.front();
  p.pop();
  for(int i=0;i<4;i++)
  {
   ptmp=pnow;
   ptmp.x+=dx[i];
   ptmp.y+=dy[i];
   if(p_ok())
   {
    if(ptmp.x==now.x-dx[k]&&ptmp.y==now.y-dy[k])
     return true;
    pvis[ptmp.x][ptmp.y]=true;
    p.push(ptmp);
   }
  }
 }
 return false;
}
 
bool ok()
{
 if(tmp.x>=0&&tmp.y>=0&&tmp.x<m&&tmp.y<n&&maze[tmp.x][tmp.y]!=1&&!vis[tmp.x][tmp.y][tmp.px][tmp.py])
  return true;
 else
  return false;
}
 
int bfs()
{
 while(!q.empty())
  q.pop();
 now.cnt=0;
 vis[now.x][now.y][now.px][now.py]=true;
 q.push(now);
 while(!q.empty())
 {
  now=q.front();
  q.pop();
  for(int i=0;i<4;i++)
  {
   tmp=now;
   tmp.x+=dx[i];
   tmp.y+=dy[i];
   if(ok())
   {
    if(p_bfs(i))//判斷人能否走到要推箱子的位置
    {
     tmp.cnt++;
     if(maze[tmp.x][tmp.y]==3)
      return tmp.cnt;
     tmp.px=now.x;tmp.py=now.y;
     vis[tmp.x][tmp.y][now.px][now.py]=true;
     q.push(tmp);
    }
   }
  }
 }
 return -1;
}
 
int main()
{
 int t;
 while(scanf("%d",&t)==1)
 {
  while(t--)
  {
   memset(vis,false,sizeof(vis));
   scanf("%d %d",&m,&n);
   for(int i=0;i<m;i++)
   {
    for(int j=0;j<n;j++)
    {
     scanf("%d",&maze[i][j]);
     if(maze[i][j]==2){now.x=i;now.y=j;}
     else if(maze[i][j]==4){now.px=i;now.py=j;}//初始化BFS箱子的第一個節點
    }
   }
   printf("%d\n",bfs());
  }
 }
 return 0;
}

 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved