Push Box

来源:互联网 发布:装饰美工职业资格证书 编辑:程序博客网 时间:2024/05/18 03:02

Push Box


Problem Description
Push Box is a classic puzzle game. This game play in a grid, there are five types of block in it, the player, the box, the hole, empty place, and the wall. In every step, player can move up, down, left, or right, if the target place is empty. Moreover, if a box in the target place, and the next place in that direction is empty, player can move to the target place, and then push the box to the next place. Remember, both of the player and boxes can't move out of the grid, or you may assume that there is a wall suround the whole grid. The objective of this game is to push every box to a hole. Now, your problem is to find the strategy to achieve the goal with shortest steps, supposed there are exactly three boxes.
 

Input
The input consists of several test cases. Each test case start with a line containing two number, n, m(1 < n, m ≤ 8), the rows and the columns of grid. Then n lines follow, each contain exact m characters, representing the type of block in it. (for empty place, X for player, * for box, # for wall, @ for hole). Each case contain exactly one X, three *, and three @. The input end with EOF.
 

Output
You have to print the length of shortest strategy in a single line for each case. (-1 if no such strategy)
 

Sample Input
4 4......*@..*@.X*@6 6...#@.@..*..#*##....##*#..X....@#...
 

Sample Output
711
 



#include <iostream>
#include <queue>
using namespace std;
const int size = 9 ;
struct Node
{
       int x, y;
       int Box[3][2];//记录三个箱子的位置 
       int step;
       char map[size][size];     
}start;
const int Go[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
char map[size][size];
int n, m;
int T_map[size][size];//临时地图 
bool visited[size][size][size][size][size][size][size][size];//八维数组,状态判重 
Node pre, next;
bool is_finish(Node a)//判断是否每个箱子都入洞 
{
     return (map[a.Box[0][0]][a.Box[0][1]] == '@' && map[a.Box[1][0]][a.Box[1][1]] == '@'  && map[a.Box[2][0]][a.Box[2][1]] == '@' );
}
bool check(int x, int y)
{
     return (x >= 0 && x < n && y >= 0 && y < m);        
}
int ans;
char Tmap[size][size];//临时地图 
void Bfs()
{
     queue <Node> Que;
     memset(visited, false, sizeof(visited));
     Que.push(start);
     while (!Que.empty()){
           pre = Que.front();
           Que.pop();
           if (is_finish(pre)){
              ans = pre.step;
              return ;                       
           }
           for (int i = 0; i < 4; i ++){
               //将前一个的地图copy到临时地图中 
               memcpy(Tmap, pre.map, sizeof(Tmap)); 
               Node Tpre = pre;
               int xx = Tpre.x + Go[i][0];
               int yy = Tpre.y + Go[i][1];
               //判断是否入队 
               if (check(xx, yy) && Tmap[xx][yy] != '#' && !(visited[xx][yy][Tpre.Box[0][0]][Tpre.Box[0][1]][Tpre.Box[1][0]][Tpre.Box[1][1]][Tpre.Box[2][0]][Tpre.Box[2][1]])){
                  //如果下一个点为箱子的话 
                  if (Tmap[xx][yy] == '*'){
                     int bx = xx + Go[i][0];
                     int by = yy + Go[i][1];
                     //判断箱子能否被推动 
                     if (check(bx, by) && Tmap[bx][by] != '#' && Tmap[bx][by] != '*'){
                        int ii = 0;
                        //查找推动的是哪个箱子 
                        for (ii = 0; ii < 3; ii ++){
                            if (Tpre.Box[ii][1] == yy && Tpre.Box[ii][0] == xx){
                               break;
                            }    
                        }
                        //推动后临时地图该点变为'*' 
                        Tmap[bx][by] = '*';        
                        //原来的两个点都变成'.'              
                        Tmap[pre.x][pre.y] = '.';
                        Tmap[xx][yy] = '.';
                        //如果前一个点是'@'(洞)的话 
                        if (T_map[pre.x][pre.y]){
                           Tmap[pre.x][pre.y] = '@';                    
                        }
                        if (T_map[xx][yy]){
                           Tmap[xx][yy] = '@';                    
                        } 
                        Tpre.Box[ii][1] = by, Tpre.Box[ii][0] = bx;
                        Tpre.x = xx, Tpre.y = yy;
                        if ((visited[xx][yy][Tpre.Box[0][0]][Tpre.Box[0][1]][Tpre.Box[1][0]][Tpre.Box[1][1]][Tpre.Box[2][0]][Tpre.Box[2][1]]))continue;                        
                     }
                     else continue;
                     }
                     next.x = xx, next.y = yy;
                     for (int ii = 0; ii < 3; ii ++){
                         next.Box[ii][0] = Tpre.Box[ii][0];
                         next.Box[ii][1] = Tpre.Box[ii][1];
                     }
                     //入队 
                     next.step = Tpre.step + 1;
                     visited[xx][yy][Tpre.Box[0][0]][Tpre.Box[0][1]][Tpre.Box[1][0]][Tpre.Box[1][1]][Tpre.Box[2][0]][Tpre.Box[2][1]] = true;
                     memcpy(next.map, Tmap, sizeof(next.map));
                     Que.push(next);
               }
           }       
     }
}
int main()
{
    while (scanf("%d%d", &n, &m) != EOF){
          memset(T_map, 0, sizeof(T_map));
          ans = -1;
          int numB = 0;
          for (int i = 0; i < n; i ++){
              scanf("%s", map[i]);
              for (int j = 0; j < m; j ++){
                  if (map[i][j] == 'X'){//记录起点 
                     start.x = i, start. y = j;
                     start.step = 0;
                     map[i][j] = '.';
                  }    
                  if (map[i][j] == '*'){//记录箱子 
                     start.Box[numB][0] = i, start.Box[numB ++][1] = j;              
                  }
                  if (map[i][j] == '@'){//记录洞 
                     T_map[i][j] = 1;              
                  } 
              }    
          }
          memcpy(start.map, map, sizeof(start.map));
          Bfs();
          printf("%d\n", ans);      
    }
    return 0;    
}

原创粉丝点击