# O - push case HDU - 1254

Pushing the box is a classic game. Today we are going to play a simple version. In an M*N room, there is a box and a porter. The job of the porter is to push the box to the designated position. Note that the porter can only push the box but not pull it, so if the box is pushed to a corner (as shown in Figure 2), the box can no longer be moved, If the box is pushed onto a wall, it can only move along the wall

Now given the structure of the room, the location of the box, the location of the porter and the location of the box to be pushed, please calculate how many squares the porter must push the box at least

Input

The first row of input data is an integer t (1 < = T < = 20), representing the number of test data. Then it is a group t test data. The first row of each group of test data is two positive integers m, n (2 < = m, n < = 7), representing the size of the room, then a matrix of M rows and N columns, representing the layout of the room, where 0 represents the empty floor, 1 represents the wall, 2 represents the starting position of the box, 3 represents the position where the box is to be pushed, 4 represents the starting position of the porter

Output for each group of test data, the output Porter needs to push at least how many boxes to push the box to the specified position. If the box cannot be pushed to the specified position, the output is - 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

# Ideas are as follows

This question A kind of A:

- When people do not push the box, the box is also an obstacle
- The box can walk a certain position repeatedly, but it can only walk once in each direction of this position (because it is a waste of steps to walk repeatedly in a certain position and a certain direction)
- Whether the box can be moved in a certain position depends on whether people can move from the position they were in after the last move to the present A kind of The position behind the box (this is because: people can only push the box when they reach the position behind the box first.)

## The following are the questions.

#include<iostream> #include<string.h> #include<queue> using namespace std; int m,n; int map[8][8],mark[8][8][4]; //Mark is used to mark whether a certain direction of a position has been passed. int mov[4][2] = { {1,0},{0,1},{-1,0},{0,-1} }; int b_x,b_y,m_x,m_y,e_x,e_y; //(B × x, B × y) position of the box, (m × x, m × y) starting position of the person, (E × x, e × y) ending point int vis[8][8]; //Whether the marker has reached a certain position struct fNode { int x,y; }; struct Node { int x,y,t; fNode last; //Where the box was before it was pushed }st,ed,s,e; //The current position of st box (the position before the box is pushed), the position to be reached after the box is pushed queue<Node> q,m_q; bool good_man(int x,int y,int b_x,int b_y) //Check the boundaries of "people" { //(B × B × y) the current position of the box (at this time, it is regarded as an "obstacle") if(x >= 0 && y >= 0 && x < m && y < n && (x != b_x || y != b_y) && map[x][y] != 1 && ! vis[x][y]) return true; return false; } bool good_box(int x,int y,int i) //Check " "" Boundary { if(x >= 0 && y >= 0 && x < m && y < n && map[x][y] != 1 && ! mark[x][y][i]) return true; return false; } bool limit(int x,int y) //Boundary check { if(x >= 0 && y >= 0 && x < m && y < n && map[x][y] != 1) return true; return false; } //This BFS man is used to judge whether "human" can be pushed forward from the last time A kind of After the person's position (sx,sy) to the current push box, it needs to reach the position behind the box (ex,ey) bool bfs_man(int sx,int sy,int ex,int ey,int b_x,int b_y) { //Initialization, assignment, tagging, queue pressing bool flag = 0; memset(vis , 0 , sizeof(vis)); while(! m_q.empty()) m_q.pop(); s.x = sx; s.y = sy; vis[s.x][s.y] = 1; m_q.push(s); while(! m_q.empty()) { s = m_q.front(); m_q.pop(); if(s.x == ex && s.y == ey) { flag = 1; break; } for(int i = 0; i < 4; i ++) { e.x = s.x + mov[i][0]; e.y = s.y + mov[i][1]; if(good_man(e.x , e.y , b_x, b_y)) { vis[e.x][e.y] = 1; m_q.push(e); } } } return flag; } //This BFS uses to determine whether the box can go from the starting position to the ending position (during this period, bfs_man is required to assist in segment determination and whether the person can reach the designated position of pushing the box) bool bfs() { //Initialization, assignment, marking, queue pressing bool Flag = 0; memset(mark , 0 , sizeof(mark)); while(! q.empty()) q.pop(); st.x = b_x; //Box current position st.y = b_y; st.last.x = m_x; //This assumes the position of the box before the last move st.last.y = m_y; st.t = 0; q.push(st); while(! q.empty()) { st = q.front(); q.pop(); if(st.x == e_x && st.y == e_y) { Flag = 1; printf("%d\n",st.t); break; } for(int i = 0; i < 4; i ++) { //(ed.x,ed.y) the position where the box will be pushed //(st.x,st.y) the position where the box will be pushed // In order to put the box (ed.x,ed.y), people need to reach the back of the box (pos.x,pos.y) ed.x = st.x + mov[i][0]; ed.y = st.y + mov[i][1]; ed.t = st.t + 1; ed.last.x = st.x; //Location of last box ed.last.y = st.y; fNode pos; pos.x = st.x - mov[i][0]; pos.y = st.y - mov[i][1]; if(good_box(ed.x , ed.y, i) && limit(pos.x , pos.y) && bfs_man(st.last.x , st.last.y , pos.x , pos.y , st.x , st.y)) { mark[ed.x][ed.y][i] = 1; q.push(ed); } } } return Flag; } int main() { // freopen("T.txt","r",stdin); int t; scanf("%d",&t); while(t--) { scanf("%d %d",&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) b_x = i , b_y = j; else if(map[i][j] == 3) e_x = i , e_y = j; else if(map[i][j] == 4) m_x = i , m_y = j; } if(! bfs()) cout<<-1<<endl; } return 0; }