zoukankan      html  css  js  c++  java
  • 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
    ", m.step);
    129         else printf("-1
    ");
    130     }
    131 
    132     return 0;
    133 }
  • 相关阅读:
    CodeForces gym Nasta Rabbara lct
    bzoj 4025 二分图 lct
    CodeForces 785E Anton and Permutation
    bzoj 3669 魔法森林
    模板汇总——快读 fread
    bzoj2049 Cave 洞穴勘测 lct
    bzoj 2002 弹飞绵羊 lct裸题
    HDU 6394 Tree 分块 || lct
    HDU 6364 Ringland
    nyoj221_Tree_subsequent_traversal
  • 原文地址:https://www.cnblogs.com/SSYYGAM/p/4512266.html
Copyright © 2011-2022 走看看