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 }
  • 相关阅读:
    linux/windows nginx安装
    linux/windows vsftpd安装
    linux 操作命令
    linux/windows java tomcat安装
    常见的Activity Action Intent常量
    Intent.ACTION_PICK
    Android实现抽奖转盘
    Android-短信验证
    Android-多平台分享(新浪微博)
    Android 手势滑动,多点触摸放大缩小图片
  • 原文地址:https://www.cnblogs.com/SSYYGAM/p/4512266.html
Copyright © 2011-2022 走看看