1254 推箱子

(c语言版)整体思路:主线是以箱子为中心做广搜,能不能扩展某个点的条件是人能不能到到达(箱子要去方向的反方向这点)这时再写一个广搜(搜人能否到达这点),(人的位置总是在箱子移动前的位置可以找到不熟的话做hdu 1026打印路径的题)(要扩展的目标终点也有,可以写)整理代码的严谨性和逻辑性就完成了。

#include<cstdio>
#include<cstring>
using namespace std;
const int N=10;
int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int book[N][N][N][N];
struct f{
 int x,y,step;
 int early;
}b[4*N*N],c[4*N*N];
int a[N][N];
int bookx[N][N];
int n,m,peox,peoy,bx,by;
int jud(int px,int py){//people+box
   int head=0,tail=1;
   c[head].x=peox,c[head].y=peoy;
   if(peox==px&&peoy==py) return 1;//如果人的初始位置满足条件就不需要扩展点了(开始忘了这个细节)
   memset(bookx,0,sizeof(bookx));
   while(head<tail){
       for(int i=0;i<4;i++)
       {
           int tx=c[head].x+next[i][0],ty=c[head].y+next[i][1];
           if(tx<1||tx>n||ty<1||ty>m||a[tx][ty]==1||bookx[tx][ty]) continue;
           if(tx==bx&&ty==by) continue;
              bookx[tx][ty]=1;
            c[tail].x=tx,c[tail++].y=ty;
           if(tx==px&&ty==py) {return 1;}
       }
       head++;
   }
   return 0;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int startx,starty,endx,endy;
        scanf("%d%d",&n,&m);//输错行列
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
            {
             scanf("%d",&a[i][j]);
             if(a[i][j]==2){startx=i,starty=j;}
             if(a[i][j]==3){endx=i,endy=j;}
             if(a[i][j]==4){peox=i,peoy=j;}
            }
      int head=0,tail=1,flag=0;
      b[head].x=startx,b[head].y=starty,b[head].step=0,b[head].early=0;
      memset(book,0,sizeof(book));
      while(head<tail){
          bx=b[head].x,by=b[head].y;//箱子位置
        if(head){peox=b[b[head].early].x,peoy=b[b[head].early].y;}//人的位置(为箱子上个的位置)
          for(int i=0;i<4;i++)
          {
              int tx=bx+next[i][0],ty=by+next[i][1];
              int px=bx-next[i][0],py=by-next[i][1];
              if(tx<1||tx>n||ty<1||ty>m||a[tx][ty]==1) continue;
              if(px<1||px>n||py<1||py>m) continue;
              if(!book[bx][by][tx][ty]&&jud(px,py)){//四维标记(人的位置(即当前箱子的位置)加箱子的位置)
                  book[bx][by][tx][ty]=1;
                  b[tail].x=tx,b[tail].y=ty,b[tail].step=b[head].step+1,b[tail++].early=head;
                  if(tx==endx&&ty==endy){
                        flag=1;break;
                  }
              }
          }
          if(flag) break;
          head++;
      }
      if(flag) printf("%d\n",b[tail-1].step);
      else printf("-1\n");
    }
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值