hdu 1254 推箱子

来源:互联网 发布:金山快译怎么翻译软件 编辑:程序博客网 时间:2024/06/02 17:40

推箱子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3811    Accepted Submission(s): 1038


Problem 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
15 50 3 0 0 01 0 1 4 00 0 1 0 01 0 2 0 00 0 0 0 0
 

Sample Output
4
搜索中套搜索,在推箱子的时候用bfs判断之前的人的位置是否能到达推箱子的时候的位置。用v[][][][]四维数组标记当前的状态,即标记箱子的位置和人的位置
AC代码:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <string>#include <algorithm>#include <queue>using namespace std;struct node{    int p_x,p_y,b_x,b_y;    int step;}start;struct node1{    int x,y;};int d[4][2]={{0,1},{0,-1},{1,0},{-1,0}};int map[10][10];int m,n;bool check(int x,int y){    if(x>=0&&x<m&&y>=0&&y<n&&map[x][y]!=1)    return true;    return false;}bool bfs2(const node &before,int px,int py)   //判断之前的人的位置是否能到达推箱子的时候的位置{   bool v[10][10];   queue<node1>q;   node1 first,next;   memset(v,false,sizeof(v));   first.x=before.p_x;   first.y=before.p_y;   v[first.x][first.y]=true;   map[before.b_x][before.b_y]=-1;          //人不能穿过箱子走过去,所以要标记   q.push(first);   while(!q.empty())   {       first=q.front();       q.pop();       if(first.x==px&&first.y==py)        {            map[before.b_x][before.b_y]=0;            return true;        }       for(int i=0;i<4;i++)       {           next.x=first.x+d[i][0];           next.y=first.y+d[i][1];           if(map[next.x][next.y]==-1) continue;           if(check(next.x,next.y)&&!v[next.x][next.y])           {               v[next.x][next.y]=true;               q.push(next);           }       }   }   map[before.b_x][before.b_y]=0;    return false;}int bfs(){    bool v[10][10][10][10];   queue<node>q;   node first,next;   memset(v,false,sizeof(v));   q.push(start);   v[start.b_x][start.b_y][start.p_x][start.p_y]=true;  //标记状态   while(!q.empty())   {       first=q.front();       q.pop();       if(map[first.b_x][first.b_y]==3)   //箱子到达终点           return first.step;       for(int i=0;i<4;i++)       {           next.b_x=first.b_x+d[i][0];           next.b_y=first.b_y+d[i][1];           next.step=first.step+1;           int x=first.b_x-d[i][0];   //推箱子的时候的位置           int y=first.b_y-d[i][1];           if(check(next.b_x,next.b_y)&&check(x,y)&&bfs2(first,x,y))   //判断之前的人的位置是否能到达当前的位置           {               next.p_x=x;               next.p_y=y;               if(!v[next.b_x][next.b_y][next.p_x][next.p_y])               {                   v[next.b_x][next.b_y][next.p_x][next.p_y]=true;                   q.push(next);               }           }       }   }   return -1;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d\n",&m,&n);        for(int i=0;i<m;i++)        for(int j=0;j<n;j++)        {            scanf("%d",&map[i][j]);            if(map[i][j]==2)     //箱子起点            {start.b_x=i;            start.b_y=j;            start.step=0;            }            else if(map[i][j]==4)   //人的起点            {                start.p_x=i;                start.p_y=j;            }        }        printf("%d\n",bfs());    }    return 0;}