HDU1254 推箱子 双BFS

HDU1254 推箱子

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

Status

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

题解

题目要求的是箱子的最短路,所以用BFS求箱子的最短路,同时也要求人能不能到达箱子的上一个位置,因为人推箱子的时候人是不动的,另外还要注意记录状态的时候要开三维vis[i][j][dir],因为从不同的位置推箱子产生后续的状态也是不同的,另外一点就是箱子走过的路可以再走,注意细节就可以啦

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define LL unsigned long long
using namespace std;
int n,m,T;
int way[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int str[10][10];
struct Node{
    int x,y,step;
    int mmap[10][10];
    bool check(){
        if(x>=0&&x<n&&y>=0&&y<m)
            return true;
        return false;
    }
}s,e,u,v,ss,ee,uu,vv;
bool bfs_people(Node n1){   //搜索人是否能到达指定位置
    queue<Node>que;
    ss=n1;
    bool flag[10][10];
    memset(flag,false,sizeof(flag));
    for(int i=0;i<n;i++){   //找到人的起点
        for(int j=0;j<m;j++)            
            if(n1.mmap[i][j]==4){
                ss.x=i;
                ss.y=j;
                ss.step=0;
            }
    }
    if(ss.x==ee.x&&ss.y==ee.y)
        return true;
    que.push(ss);
    flag[ss.x][ss.y]=true;
    while(!que.empty()){
        uu=que.front();
        que.pop();
        for(int i=0;i<4;i++){
            vv=uu;
            vv.step++;
            vv.x+=way[i][0];
            vv.y+=way[i][1];
            if(vv.check()&&flag[vv.x][vv.y]==false&&(n1.mmap[vv.x][vv.y]!=1&&n1.mmap[vv.x][vv.y]!=2)){ //目标点不是墙也不是箱子
                flag[vv.x][vv.y]=true;
                if(vv.x==ee.x&&vv.y==ee.y)
                    return true;
                que.push(vv);
            }
        }
    }
    return false;
}

int bfs_box(){ //搜索箱子
    int flag[10][10][4];
    queue<Node>que;
    que.push(s);
    memset(flag,false,sizeof(flag));
    while(!que.empty()){
        u=que.front();
        que.pop();
        for(int i=0;i<4;i++){
            v=u;
            v.x+=way[i][0];
            v.y+=way[i][1];
            v.step++;
            if(v.check()&&str[v.x][v.y]!=1&&flag[v.x][v.y][i]==false){
                //人的目标位置
                ee.x=u.x-way[i][0];
                ee.y=u.y-way[i][1];
                if(ee.check()==false)
                    continue;
                if(bfs_people(v)){
                    //更新地图,箱子和人的位置
                    swap(v.mmap[v.x][v.y],v.mmap[u.x][u.y]);
                    swap(v.mmap[ee.x][ee.y],v.mmap[ss.x][ss.y]);
                    flag[v.x][v.y][i]=true;
                    if(str[v.x][v.y]==3)
                        return v.step;
                    que.push(v);
                }
            }
        }
    }
    return -1;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                scanf("%d",&str[i][j]);
                s.mmap[i][j]=str[i][j];
                if(str[i][j]==2){   //标注箱子起点
                    s.x=i;
                    s.y=j;
                    s.step=0;
                }
            }
            printf("%d\n",bfs_box());
    }
    return 0;
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值