hdu 1254 推箱子(方向)

 
 
 

推箱子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6027    Accepted Submission(s): 1721
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
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
 
Author
Ignatius.L & weigang Lee
 
Recommend
Ignatius.L   |   We have carefully selected several similar problems for you:  1180 1253 1026 1175 1072 
 
 
 
 
 
 
 
 

 

  1 /*
  2 *State: HDU1254     31MS    4920K    2558 B    C++
  3 *题目大意:
  4 *        推箱子,1代表墙,2代表箱子,3代表终点,4代表人。
  5 *解题思路:
  6 *        要先搜出人可以到达的位置,来判断箱子能否朝这个方向
  7 *        前进,之后还要注意一个状态的标志,一个位置可以走四次
  8 *        因为有四个不同的方向(这是此题的亮处吧)。
  9 *解题感想;
 10 *        贡献了好多个wa,就是因为没有想对状态。
 11 1.箱子前方没有障碍物;
 12 2.箱子后方没有障碍物;
 13 3.人能到达箱子后面。
 14 
 15 1)采用DFS/BFS判断人是否可以到达箱子的对面时,要明确人不能穿过箱子,即对箱子标记flag[p.Bx][p.By] = 1;
 16 
 17 (2)求箱子的对面求坐标时要保证这个坐标没有超边界。
 18 
 19 (3)DFS时不需要回溯。
 20 
 21 (4)推箱子时,人的位置不会跟随箱子的移动而移动。
 22 */
 23 
 24 #include <iostream>
 25 #include <stdio.h>
 26 #include <memory.h>
 27 #include <queue>
 28 using namespace std;
 29 
 30 int xx[8] = {-1, 0, 1, 0, -1, 0, 1, 0};
 31 int yy[8] = {0, -1, 0, 1, 0, -1, 0, 1};
 32 
 33 bool map[10][10][5];    //map[][][]三维数组,记录箱子(x,y)坐标和方向
 34 int a[10][10], b[10][10], c[10][10];
 35 int x1, y1, x2, y2, tx, ty, px, py, ax, ay;
 36 int N, M;
 37 bool flag;
 38 
 39 struct node
 40 {
 41     int x, y, px, py, step; //分别保存箱子的坐标(x,y)、人的坐标(px,py)、步数
 42 } n, m;
 43 
 44 bool dfs(int x, int y)  //深搜:判断人是否能够到达箱子的后面
 45 {
 46     if(x == tx && y == ty) return true;     //到达箱子后面
 47     if(x<0 || x>=N || y<0 || y>=M) return false;    //越界的返回false
 48     if(x == ax && y == ay) return false;    //该点是箱子挡住路了
 49     if(b[x][y] == 1) return false;          //该点是墙壁挡住路了
 50     b[x][y] = 1;    //走过的标记不能再走
 51     return (dfs(x+1,y) || dfs(x-1,y) || dfs(x,y+1) || dfs(x,y-1));  //往内深搜
 52 }
 53 
 54 void set_bc()   //初始化深搜时用到的数组b[][]
 55 {
 56     int i, j;
 57     for(i = 0; i < N; i++)
 58         for(j = 0; j < M; j++)
 59             b[i][j] = c[i][j];
 60 }
 61 
 62 int main()
 63 {
 64     int i, j, k, t;
 65     scanf("%d", &t);
 66     while(t--)
 67     {
 68         scanf("%d %d", &N, &M);
 69         for(i = 0; i < N; i++)
 70         {
 71             for(j = 0; j < M; j++)
 72             {
 73                 cin>>a[i][j];
 74                 c[i][j] = b[i][j] = a[i][j];
 75                 if(a[i][j] == 2)
 76                     x1 = i, y1 = j;     //箱子的坐标
 77                 if(a[i][j] == 3)
 78                     x2 = i, y2 = j;     //目标的坐标
 79                 if(a[i][j] == 4)
 80                     px = i, py = j;     //人的坐标
 81                 for(k = 0; k < 4; k++)
 82                     map[i][j][k] = false;   //初始化map[][][]
 83             }
 84         }
 85         flag = false;
 86         n.x = x1;
 87         n.y = y1;
 88         n.step = 0; //更新第一个push进去的点
 89         n.px = px;
 90         n.py = py;
 91         queue<node> Q;
 92         Q.push(n);
 93         while(!Q.empty())
 94         {
 95             m = Q.front();
 96             Q.pop();
 97             if(m.x == x2 && m.y == y2)  //箱子到达目标
 98             {
 99                 flag = true;
100                 break;
101             }
102             for(i = 0; i < 4; i++)
103             {
104                 n.x = m.x + xx[i];    //后来箱子的位置
105                 n.y = m.y + yy[i];
106                 //i+2 刚好是箱子的反方向位置
107                 tx = m.x + xx[i+2];    //后来人的位置
108                 ty = m.y + yy[i+2];
109                 ax = m.x;        //原来箱子的位置
110                 ay = m.y;
111                 n.px = m.px;    //原来人的位置
112                 n.py = m.py;
113                 n.step = m.step + 1;
114                 if(n.x>=0 && n.x<N && n.y>=0 && n.y<M && !map[n.x][n.y][i] && a[n.x][n.y]!=1)   //箱子前方没问题
115                 {
116                     set_bc();   //初始化b[][]数组
117                     if(tx>=0 && tx<N && ty>=0 && ty<M && a[tx][ty]!=1 && dfs(n.px, n.py))   //人能到达箱子的后方
118                     {
119                         //则箱子能推倒该点(n.px,n.py)
120                         n.px = tx;
121                         n.py = ty;
122                         map[n.x][n.y][i] = true;    //标记该点和来的这个i方向
123                         Q.push(n);
124                     }
125                 }
126             }
127         }
128         if(flag) printf("%d\n", m.step);
129         else printf("-1\n");
130     }
131 
132     return 0;
133 }

 

posted @ 2015-05-18 16:31  zach96  阅读(274)  评论(0编辑  收藏  举报