HDU 1254 推箱子(双层BFS)

推箱子 Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u

Description

推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.

现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.


 

Input

输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.
 

Output

对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.
 

Sample Input

      
      
1 5 5 0 3 0 0 0 1 0 1 4 0 0 0 1 0 0 1 0 2 0 0 0 0 0 0 0
 

Sample Output

      
      
4



思路:

分成2部分 ,首先bfs 搜索箱子能够移动到的地方 然后对人进行bfs 看人是否能走到箱子边上 并且让箱子移动到新的位置  
用vis[30][30][30][30]去标记 当人在某个位置箱子在某个位置时的状态 


AC代码:0MS

 #include<iostream>
 #include<cstdio>
 #include<cmath>
 #include<cstring>
 #include<queue>
 #include<algorithm>
 using namespace std;
 bool pvis[30][30],bvis[30][30],vis[30][30][30][30];<span><span class="comment">//四维 前2维是箱子的位置 后2维是人的位置 表示在人在某个位置而箱子在某个位置这个状态是否走过</span><span>  </span></span>
 int map[30][30];
 int n,m;
 int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0} };//这个思路,在这里不要用这组方向dir[4][2]={{1,0},{-1,0},{0,1},{0,-1} };无限WA了将近十次,最后改了这里居然过了
    ,现在我也不知道为何,等以后知道了再来修改,要是哪位大神知道为何不能用这组方向求指教。谢谢了

 struct person{
     int x, y;
 }pq,ptemp;
 struct box{
     int x;
     int y;
     int px;
     int py;
     int step;
 }q,temp;
 bool pok(int xx,int yy)
 {
     if(xx<0 || xx>=n || yy<0 || yy>=m || pvis[xx][yy] || map[xx][yy]==1 || (xx==temp.x && yy==temp.y)) return false;<span><span class="comment">// 最后一个条件保证人不会穿越箱子</span><span>  </span></span>
     return true;
 }
 int p_bfs(int x,int y,int fx)<span><span class="comment">//x  y是 推动后箱子的位置</span><span>  </span></span>
 {
     memset(pvis,0,sizeof(pvis));
     queue<person> que;
     pq.x=temp.px,pq.y=temp.py;
     pvis[pq.x][pq.y]=true;
     que.push(pq);
     while(!que.empty())
     {
         ptemp=que.front();
         que.pop();
         if(ptemp.x==temp.x-dir[fx][0] && ptemp.y==temp.y-dir[fx][1]) return 1;
         for(int i=0;i<4;i++)
         {
             pq.x=ptemp.x+dir[i][1];
             pq.y=ptemp.y+dir[i][0];
             if(pok(pq.x,pq.y))
             {
                 que.push(pq);
                 pvis[pq.x][pq.y]=true;
             }
         }
     }
     return 0;
 }
 bool ok(int xx,int yy)
 {
     if(xx<0 || xx>=n || yy<0 || yy>=m || map[xx][yy]==1 || vis[xx][yy][temp.px][temp.py]) return false;
     return true;
 }
 void bfs()
 {
     vis[q.x][q.y][q.px][q.py]=true;
     q.step=0;
     queue<box> que;
     que.push(q);
     while(!que.empty())
     {
         temp=que.front();
         que.pop();
         if(map[temp.x][temp.y]==3){ printf("%d\n",temp.step);return;}
         for(int i=0;i<4;i++)
         {
             int xx,yy;
             xx=temp.x+dir[i][0];
             yy=temp.y+dir[i][1];
             if(ok(xx,yy))<span><span class="comment">// 箱子能走</span><span></span></span>
             {
                 if(p_bfs(xx,yy,i))<span><span class="comment">//如果人能走到箱子边上并且能推动箱子</span><span>  </span></span>
                 {
                     q.px=temp.x;
                     q.py=temp.y;
                     q.step=temp.step+1;
                     q.x=xx;
                     q.y=yy;
                     que.push(q);
                     vis[xx][yy][temp.px][temp.py]=true;
                 }
                 
             }
         }
     }
     printf("-1\n");
 }
 int main()
 {
         int t;
         scanf("%d",&t);
         while(t--)
         {
             memset(vis,0,sizeof(vis));
             scanf("%d %d",&n,&m);
             for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    scanf("%d",&map[i][j]);
                    if(map[i][j]==2)
                        q.x=i,q.y=j;
                    else if(map[i][j]==4)
                        q.px=i,q.py=j;
                }
             }
             bfs();
         }
     return 0;
 }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值