Problem:
Problem C:
Push!!
Mr. Schwarz was a famous powerful pro wrestler. He starts a part time job as a warehouseman.
His task is to move a cargo to a goal by repeatedly pushing the cargo in the warehouse, of course,
without breaking the walls and the pillars of the warehouse.
There may be some pillars in the warehouse. Except for the locations of the pillars, the floor of
the warehouse is paved with square tiles whose size fits with the cargo. Each pillar occupies the
same area as a tile.
Initially, the cargo is on the center of a tile. With one push, he can move the cargo onto the
center of an adjacent tile if he is in proper position. The tile onto which he will move the cargo
must be one of (at most) four tiles (i.e., east, west, north or south) adjacent to the tile where
the cargo is present.
To push, he must also be on the tile adjacent to the present tile. He can only push the cargo in
the same direction as he faces to it and he cannot pull it. So, when the cargo is on the tile next
to a wall (or a pillar), he can only move it along the wall (or the pillar). Furthermore, once he
places it on a corner tile, he cannot move it anymore.
He can change his position, if there is a path to the position without obstacles (such as the cargo
and pillars) in the way. The goal is not an obstacle. In addition, he can move only in the four
directions (i.e., east, west, north or south) and change his direction only at the center of a tile.
As he is not so young, he wants to save his energy by keeping the number of required pushes
as small as possible. But he does not mind the count of his pedometer, because walking is very
light exercise for him.
Your job is to write a program that outputs the minimum number of pushes required to move
the cargo to the goal, if ever possible.
Input
The input consists of multiple maps, each representing the size and the arrangement of the
warehouse. A map is given in the following format.
w h
d
11
d
12
d
13
...
d
1
w
d
21
d
22
d
23
...
d
2
w
...
d
h
1
d
h
2
d
h
3
...
d
h
w
The integers w and h are the lengths of the two sides of the floor of the warehouse in terms of
widths of floor tiles.
w
and
h
are less than or equal to 7. The integer
d
ij
represents what is
initially on the corresponding floor area in the following way.
0: nothing (simply a floor tile)
1: a pillar
2: the cargo
3: the goal
4: the warehouseman (Mr. Schwarz)
Each of the integers 2, 3 and 4 appears exactly once as
d
ij
in the map. Integer numbers in an
input line are separated by at least one space character. The end of the input is indicated by a
line containing two zeros.
Output
For each map, your program should output a line containing the minimum number of pushes.
If the cargo cannot be moved to the goal, -1 should be output instead.
Sample Input
5 5
0 0 0 0 0
4 2 0 1 1
0 1 0 0 0
1 0 0 0 3
1 0 0 0 0
5 3
4 0 0 0 0
2 0 0 0 0
0 0 0 0 3
7 5
1 1 4 1 0 0 0
1 1 2 1 0 0 0
3 0 0 0 0 0 0
0 1 0 1 0 0 0
0 0 0 1 0 0 0
6 6
0 0 0 0 0 3
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 2
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;

constexpr long double EPS = 1e-15;
const long double PI = acos(-1);
constexpr int inf = 2e9;
constexpr ll INF = 2e18;
constexpr ll MOD = 1e9+7;
constexpr ll MOD1 = 998244353;
typedef pair<ll,ll> P;

//#define all(v) (v).begin(), (v).end()
#define rep(i,a,b) for (int i = (a); i < (b); i++)
#define REP(i,n) rep(i,0,n)
#define sz(s) (s).size()
#define pb push_back
#define fi first
#define se second
//#define mp make_pair

int w,h;
int gh,gw;
map<string,int> mp;
int dh[4] = {0,0,1,-1};
int dw[4] = {1,-1,0,0};

int id (int hh, int ww) {
    return w * hh + ww;
}

void out(string s) {
    REP(i,h) {
        REP(j,w) {
            cout << s[id(i,j)];
        }
        cout << endl;
    }
    cout << endl;
}

void solve() {
while (cin >> w >> h) {
    if (w == 0 && h == 0) break;
    mp.clear();
    string s;
    REP(hh,h) {
        REP(ww,w) {
            char c;
            cin >> c;
            if (c == '3') {
                gh = hh;
                gw = ww;
            }
            s +=c;
        }
    }
    int ans = inf;
    mp[s] = 0;
    queue<pair<string,int>> que;
    que.push({s,0});
    while (!que.empty()) {
        string maze = que.front().fi;
        int cost = que.front().se;
        que.pop();
        if (cost > mp[maze]) continue;
        
        int hh = -1,ww;
        REP(i,h) {
            REP(j,w) {
                if (maze[id(i,j)] == '4') {
                    hh = i;
                    ww = j;
                    break;
                }
            }
            if (hh != -1) break;
        }
        for (int i = 0; i < 4; i++) {

            int th = hh + dh[i];
            int tw = ww + dw[i];
            if (th < 0 || th >= h || tw < 0 || tw >= w) continue;
            if (maze[id(th,tw)] == '1') continue;

            if (maze[id(th,tw)] == '0' || maze[id(th,tw)] == '3') {
                string tmp = maze;
                swap(tmp[id(th,tw)], tmp[id(hh,ww)]);
                if (mp.count(tmp)) continue;
                mp[tmp] = cost;
                que.push({tmp, cost});
            }

            if (maze[id(th,tw)] == '2') {
                int tth = th + dh[i];
                int ttw = tw + dw[i];
                if (tth < 0 || tth >= h || ttw < 0 || ttw >= w) continue;
                if (maze[id(tth,ttw)] == '1') continue;
                string tmp = maze;
                swap(tmp[id(tth,ttw)], tmp[id(th,tw)]);
                swap(tmp[id(th,tw)], tmp[id(hh,ww)]);
                if (mp.count(tmp)) continue;
                mp[tmp] = cost + 1;
                if (tth == gh && ttw == gw) {
                    ans = min(ans, cost + 1);
                    continue;
                }
                que.push({tmp, cost + 1});
            }

        }
    }
    if (ans == inf) cout << -1 << endl;
    else cout << ans << endl;
}
}


int main(int argc, char *argv[]){

    // /* Regular */
    // int case_num = 1;
    // if (argc > 1 && stoi(argv[1])) cin >> case_num;
    // REP(case_no, case_num) {
    //   cerr << endl << "case " << case_no + 1 << endl;
    //   solve();
    // }

    /* AOJ */
    solve();

    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 9176
final_rank: 11

code_snippet: #include <iostream>
#include <algorithm>
#include <queue>
#define f first
#define s second
#define INF (1e9)
#define N 7
using namespace std;
typedef pair<int,int> P;
int bfs(int,int,int,int,int,int);
bool check(int,int,int,int,int,int);
int w,h,data[N][N],d[N][N],cnt[N][N];
int dy[4]={-1,0,1,0};
int dx[4]={0,1,0,-1};
typedef struct data{
  int cy,cx,wy,wx;
} dat;

int main(){
  int sy,sx,gy,gx,wy,wx,ans;
  while(1){
    cin>>w>>h;
    if(!w&&!h) break;
    for(int i=0;i<h;i++)
      for(int j=0;j<w;j++){
	cin >> data[i][j];
	if(data[i][j]==2) sy=i,sx=j;
	else if(data[i][j]==3) gy=i,gx=j;
	else if(data[i][j]==4) wy=i,wx=j;
	d[i][j]=INF;
      }
    ans=bfs(sy,sx,wy,wx,gy,gx);
    cout << ans << endl;
  }
  return 0;
}

int bfs(int sy,int sx,int wy,int wx,int gy,int gx){
  queue<dat > q;
  int flag;
  dat k={sy,sx,wy,wx};
  q.push(k);
  d[sy][sx]=0;
  for(int i=0;i<N;i++)
    for(int j=0;j<N;j++) cnt[i][j]=0;
  while(!q.empty()){
    dat u=q.front();
    q.pop();
    flag=0;
    for(int i=0;i<4;i++){
      int ny=u.cy+dy[i],nx=u.cx+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1) continue;
      if(check(u.wy,u.wx,u.cy-dy[i],u.cx-dx[i],u.cy,u.cx)){
	d[ny][nx]=d[u.cy][u.cx]+1;
	cnt[nx][ny]++;
	if(cnt[nx][ny]==500){
	  flag=1;
	  break;
	}
	if(d[gy][gx]!=INF){
	  flag=2;
	  break;
	}
	dat t={ny,nx,u.cy-dy[i],u.cx-dx[i]};
	q.push(t);
      }
    }
    if(flag) break;
  }
  if(flag==2) return d[gy][gx];
  if(flag) return -1;
  if(d[gy][gx]!=INF) return d[gy][gx];
  return -1;
}

bool check(int sy,int sx,int gy,int gx,int xy,int xx){
  if(gy<0||gx<0||h<=gy||w<=gx) return false;
  if(data[gy][gx]==1) return false;
  bool c[N][N];
  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++) c[i][j]=false;
  queue<P > q;
  q.push(make_pair(sy,sx));
  c[sy][sx]=true;
  while(!q.empty()){
    P u=q.front();
    q.pop();
    for(int i=0;i<4;i++){
      int ny=u.f+dy[i],nx=u.s+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1||(ny==xy&&nx==xx)) continue;
      if(c[ny][nx]==true) continue;
      c[ny][nx]=true;
      q.push(make_pair(ny,nx));
    }
  }
  if(c[gy][gx]==true) return true;
  return false;
}
accuracy: 1
time_ms: 10
memory_kb: 1280
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <queue>
#define f first
#define s second
#define INF (1e9)
#define N 7
using namespace std;
typedef pair<int,int> P;
int bfs(int,int,int,int,int,int);
bool check(int,int,int,int,int,int);
int w,h,data[N][N],d[N][N],cnt[N][N];
int dy[4]={-1,0,1,0};
int dx[4]={0,1,0,-1};
typedef struct data{
  int cy,cx,wy,wx;
} dat;

int main(){
  int sy,sx,gy,gx,wy,wx,ans;
  while(1){
    cin>>w>>h;
    if(!w&&!h) break;
    for(int i=0;i<h;i++)
      for(int j=0;j<w;j++){
	cin >> data[i][j];
	if(data[i][j]==2) sy=i,sx=j;
	else if(data[i][j]==3) gy=i,gx=j;
	else if(data[i][j]==4) wy=i,wx=j;
	d[i][j]=INF;
      }
    ans=bfs(sy,sx,wy,wx,gy,gx);
    cout << ans << endl;
  }
  return 0;
}

int bfs(int sy,int sx,int wy,int wx,int gy,int gx){
  queue<dat > q;
  int flag;
  dat k={sy,sx,wy,wx};
  q.push(k);
  d[sy][sx]=0;
  for(int i=0;i<N;i++)
    for(int j=0;j<N;j++) cnt[i][j]=0;
  while(!q.empty()){
    dat u=q.front();
    q.pop();
    flag=0;
    for(int i=0;i<4;i++){
      int ny=u.cy+dy[i],nx=u.cx+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1) continue;
      if(check(u.wy,u.wx,u.cy-dy[i],u.cx-dx[i],u.cy,u.cx)){
	d[ny][nx]=d[u.cy][u.cx]+1;
	cnt[nx][ny]++;
	if(cnt[nx][ny]==1000){
	  flag=1;
	  break;
	}
	if(d[gy][gx]!=INF){
	  flag=2;
	  break;
	}
	dat t={ny,nx,u.cy-dy[i],u.cx-dx[i]};
	q.push(t);
      }
    }
    if(flag) break;
  }
  if(flag==2) return d[gy][gx];
  if(flag) return -1;
  if(d[gy][gx]!=INF) return d[gy][gx];
  return -1;
}

bool check(int sy,int sx,int gy,int gx,int xy,int xx){
  if(gy<0||gx<0||h<=gy||w<=gx) return false;
  if(data[gy][gx]==1) return false;
  bool c[N][N];
  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++) c[i][j]=false;
  queue<P > q;
  q.push(make_pair(sy,sx));
  c[sy][sx]=true;
  while(!q.empty()){
    P u=q.front();
    q.pop();
    for(int i=0;i<4;i++){
      int ny=u.f+dy[i],nx=u.s+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1||(ny==xy&&nx==xx)) continue;
      if(c[ny][nx]==true) continue;
      c[ny][nx]=true;
      q.push(make_pair(ny,nx));
    }
  }
  if(c[gy][gx]==true) return true;
  return false;
}
accuracy: 1
time_ms: 10
memory_kb: 1280
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <queue>
#define f first
#define s second
#define INF (1e9)
#define N 7
using namespace std;
typedef pair<int,int> P;
int bfs(int,int,int,int,int,int);
bool check(int,int,int,int,int,int);
int w,h,data[N][N],d[N][N],cnt[N][N];
int dy[4]={-1,0,1,0};
int dx[4]={0,1,0,-1};
typedef struct data{
  int cy,cx,wy,wx;
} dat;

int main(){
  int sy,sx,gy,gx,wy,wx,ans;
  while(1){
    cin>>w>>h;
    if(!w&&!h) break;
    for(int i=0;i<h;i++)
      for(int j=0;j<w;j++){
	cin >> data[i][j];
	if(data[i][j]==2) sy=i,sx=j;
	else if(data[i][j]==3) gy=i,gx=j;
	else if(data[i][j]==4) wy=i,wx=j;
	d[i][j]=INF;
      }
    ans=bfs(sy,sx,wy,wx,gy,gx);
    cout << ans << endl;
  }
  return 0;
}

int bfs(int sy,int sx,int wy,int wx,int gy,int gx){
  queue<dat > q;
  int flag;
  dat k={sy,sx,wy,wx};
  q.push(k);
  d[sy][sx]=0;
  for(int i=0;i<N;i++)
    for(int j=0;j<N;j++) cnt[i][j]=0;
  while(!q.empty()){
    dat u=q.front();
    q.pop();
    flag=0;
    for(int i=0;i<4;i++){
      int ny=u.cy+dy[i],nx=u.cx+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1) continue;
      if(check(u.wy,u.wx,u.cy-dy[i],u.cx-dx[i],u.cy,u.cx)){
	d[ny][nx]=d[u.cy][u.cx]+1;
	cnt[nx][ny]++;
	if(cnt[nx][ny]==10000){
	  flag=1;
	  break;
	}
	if(d[gy][gx]!=INF){
	  flag=2;
	  break;
	}
	dat t={ny,nx,u.cy-dy[i],u.cx-dx[i]};
	q.push(t);
      }
    }
    if(flag) break;
  }
  if(flag==2) return d[gy][gx];
  if(flag) return -1;
  if(d[gy][gx]!=INF) return d[gy][gx];
  return -1;
}

bool check(int sy,int sx,int gy,int gx,int xy,int xx){
  if(gy<0||gx<0||h<=gy||w<=gx) return false;
  if(data[gy][gx]==1) return false;
  bool c[N][N];
  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++) c[i][j]=false;
  queue<P > q;
  q.push(make_pair(sy,sx));
  c[sy][sx]=true;
  while(!q.empty()){
    P u=q.front();
    q.pop();
    for(int i=0;i<4;i++){
      int ny=u.f+dy[i],nx=u.s+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1||(ny==xy&&nx==xx)) continue;
      if(c[ny][nx]==true) continue;
      c[ny][nx]=true;
      q.push(make_pair(ny,nx));
    }
  }
  if(c[gy][gx]==true) return true;
  return false;
}
accuracy: 1
time_ms: 30
memory_kb: 1356
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>
#include <queue>
#define f first
#define s second
#define INF (1e9)
#define N 7
using namespace std;
typedef pair<int,int> P;
int bfs(int,int,int,int,int,int);
bool check(int,int,int,int,int,int);
int w,h,data[N][N],d[N][N],cnt[N][N];
int dy[4]={-1,0,1,0};
int dx[4]={0,1,0,-1};
typedef struct data{
  int cy,cx,wy,wx;
} dat;

int main(){
  int sy,sx,gy,gx,wy,wx,ans;
  while(1){
    cin>>w>>h;
    if(!w&&!h) break;
    for(int i=0;i<h;i++)
      for(int j=0;j<w;j++){
	cin >> data[i][j];
	if(data[i][j]==2) sy=i,sx=j;
	else if(data[i][j]==3) gy=i,gx=j;
	else if(data[i][j]==4) wy=i,wx=j;
	d[i][j]=INF;
      }
    ans=bfs(sy,sx,wy,wx,gy,gx);
    cout << ans << endl;
  }
  return 0;
}

int bfs(int sy,int sx,int wy,int wx,int gy,int gx){
  queue<dat > q;
  int flag;
  dat k={sy,sx,wy,wx};
  q.push(k);
  d[sy][sx]=0;
  for(int i=0;i<N;i++)
    for(int j=0;j<N;j++) cnt[i][j]=0;
  while(!q.empty()){
    dat u=q.front();
    q.pop();
    flag=0;
    for(int i=0;i<4;i++){
      int ny=u.cy+dy[i],nx=u.cx+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1) continue;
      if(check(u.wy,u.wx,u.cy-dy[i],u.cx-dx[i],u.cy,u.cx)){
	d[ny][nx]=d[u.cy][u.cx]+1;
	cnt[nx][ny]++;
	if(cnt[nx][ny]==100000){
	  flag=1;
	  break;
	}
	if(d[gy][gx]!=INF){
	  flag=2;
	  break;
	}
	dat t={ny,nx,u.cy-dy[i],u.cx-dx[i]};
	q.push(t);
      }
    }
    if(flag) break;
  }
  if(flag==2) return d[gy][gx];
  if(flag) return -1;
  if(d[gy][gx]!=INF) return d[gy][gx];
  return -1;
}

bool check(int sy,int sx,int gy,int gx,int xy,int xx){
  if(gy<0||gx<0||h<=gy||w<=gx) return false;
  if(data[gy][gx]==1) return false;
  bool c[N][N];
  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++) c[i][j]=false;
  queue<P > q;
  q.push(make_pair(sy,sx));
  c[sy][sx]=true;
  while(!q.empty()){
    P u=q.front();
    q.pop();
    for(int i=0;i<4;i++){
      int ny=u.f+dy[i],nx=u.s+dx[i];
      if(ny<0||nx<0||h<=ny||w<=nx||data[ny][nx]==1||(ny==xy&&nx==xx)) continue;
      if(c[ny][nx]==true) continue;
      c[ny][nx]=true;
      q.push(make_pair(ny,nx));
    }
  }
  if(c[gy][gx]==true) return true;
  return false;
}
accuracy: 1
time_ms: 220
memory_kb: 3692
final_rank: 10

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

typedef pair<int, int> P;

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

int H, W;
int field[8][8];
bool arrive[8][8][8][8][8][8];

void init(){
  memset(field, 0, sizeof(field));
  memset(arrive, false, sizeof(arrive));
}

void canArrive(int bx, int by, int sx, int sy){
  int tmp_field[8][8];
  memset(tmp_field, 0, sizeof(tmp_field));
  for(int i = 0 ; i < H ; i++){
    for(int j = 0 ; j < W ; j++){
      if(field[i][j] != 1) tmp_field[i][j] = 0;
      else tmp_field[i][j] = field[i][j];
    }
  }
  
  tmp_field[by][bx] = 2;

  queue<P> que;
  que.push(P(sx, sy));
  while(!que.empty()){
    P q = que.front(); que.pop();
    arrive[by][bx][sy][sx][q.second][q.first] = true;
    
    for(int i = 0 ; i < 4 ; i++){
      int nx = q.first + dx[i], ny = q.second + dy[i];
      if(nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
      if(tmp_field[ny][nx] != 0) continue;
      if(arrive[by][bx][sy][sx][ny][nx]) continue;
      que.push(P(nx, ny));
    }    
  }
}

struct State{
  int x, y, sx, sy, cost;
  State(int x, int y, int sx, int sy, int cost) : x(x), y(y), sx(sx), sy(sy), cost(cost){}
};

const bool operator < (const State &a, const State &b){
  return a.cost > b.cost;
}

int bfs(){
  int sx, sy, bx, by;
  for(int i = 0 ; i < H ; i++){
    for(int j = 0 ; j < W ; j++){
      if(field[i][j] == 2) bx = j, by = i;
      if(field[i][j] == 4) sx = j, sy = i;
    }
  }
  
  priority_queue<State> que;
  que.push(State(bx, by, sx, sy, 0));
  
  bool used[8][8][8][8];
  memset(used, false, sizeof(used));
  
  while(!que.empty()){
    State p = que.top(); que.pop();

    if(field[p.y][p.x] == 3) return p.cost;    

    if(used[p.y][p.x][p.sy][p.sx]) continue;
    used[p.y][p.x][p.sy][p.sx] = true;
    
    for(int i = 0 ; i < 4 ; i++){
      int nx1, nx2, ny1, ny2;
      nx1 = p.x + dx[i], ny1 = p.y + dy[i];
      nx2 = p.x - dx[i], ny2 = p.y - dy[i];
      if(nx1 < 0 || nx1 >= W || ny1 < 0 || ny1 >= H ||
	 nx2 < 0 || nx2 >= W || ny2 < 0 || ny2 >= H) continue;
      if(field[ny1][nx1] == 1) continue;
      if(field[ny2][nx2] == 1) continue;
      if(!arrive[p.y][p.x][p.sy][p.sx][ny2][nx2]) continue;      
      que.push(State(nx1, ny1, nx2, ny2, p.cost+1));
    }    
  }
  return -1;
}

int main(){
  while(cin >> W >> H, W|H){
    init();
    
    for(int i = 0 ; i < H ; i++)
      for(int j = 0 ; j < W ; j++) cin >> field[i][j];
    
    for(int by = 0 ; by < H ; by++){
      for(int bx = 0 ; bx < W ; bx++){
	if(field[by][bx] == 1) continue;
	for(int sy = 0 ; sy < H ; sy++){
	  for(int sx = 0 ; sx < W ; sx++){
	    if(sy == by && sx == bx) continue;
	    if(field[sy][sx] == 1) continue;
	    canArrive(bx, by, sx, sy);
	  }
	}
      }
    }
    cout << bfs() << endl; 
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1492
final_rank: 6

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

typedef pair<int, int> P;

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

int H, W;
int field[8][8];
bool arrive[8][8][8][8][8][8];

void init(){
  memset(field, 0, sizeof(field));
  memset(arrive, false, sizeof(arrive));
}

bool canArrive(int bx, int by, int sx, int sy){
  int tmp_field[8][8];
  memset(tmp_field, 0, sizeof(tmp_field));
  for(int i = 0 ; i < H ; i++){
    for(int j = 0 ; j < W ; j++){
      if(field[i][j] != 1) tmp_field[i][j] = 0;
      else tmp_field[i][j] = field[i][j];
    }
  }
  
  tmp_field[by][bx] = 2;

  queue<P> que;
  que.push(P(sx, sy));
  while(!que.empty()){
    P q = que.front(); que.pop();
    arrive[by][bx][sy][sx][q.second][q.first] = true;
    
    for(int i = 0 ; i < 4 ; i++){
      int nx = q.first + dx[i], ny = q.second + dy[i];
      if(nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
      if(tmp_field[ny][nx] != 0) continue;
      if(arrive[by][bx][sy][sx][ny][nx]) continue;
      que.push(P(nx, ny));
    }    
  }
}


struct State{
  int x, y, sx, sy, cost;
  State(int x, int y, int sx, int sy, int cost) : x(x), y(y), sx(sx), sy(sy), cost(cost){}
};

const bool operator < (const State &a, const State &b){
  return a.cost > b.cost;
}

int bfs(){
  int sx, sy, bx, by;
  for(int i = 0 ; i < H ; i++){
    for(int j = 0 ; j < W ; j++){
      if(field[i][j] == 2) bx = j, by = i;
      if(field[i][j] == 4) sx = j, sy = i;
    }
  }
  
  priority_queue<State> que;
  que.push(State(bx, by, sx, sy, 0));
  
  bool used[8][8][8][8];
  memset(used, false, sizeof(used));
  
  while(!que.empty()){
    State p = que.top(); que.pop();

    if(field[p.y][p.x] == 3) return p.cost;    

    if(used[p.y][p.x][p.sy][p.sx]) continue;
    used[p.y][p.x][p.sy][p.sx] = true;
    
    for(int i = 0 ; i < 4 ; i++){
      int nx1, nx2, ny1, ny2;
      nx1 = p.x + dx[i], ny1 = p.y + dy[i];
      nx2 = p.x - dx[i], ny2 = p.y - dy[i];
      if(nx1 < 0 || nx1 >= W || ny1 < 0 || ny1 >= H ||
	 nx2 < 0 || nx2 >= W || ny2 < 0 || ny2 >= H) continue;
      if(field[ny1][nx1] == 1) continue;
      if(field[ny2][nx2] == 1) continue;
      if(!arrive[p.y][p.x][p.sy][p.sx][ny2][nx2]) continue;      
      que.push(State(nx1, ny1, nx2, ny2, p.cost+1));
    }    
  }
  return -1;
}

int main(){
  while(cin >> W >> H, W|H){
    init();
    
    for(int i = 0 ; i < H ; i++)
      for(int j = 0 ; j < W ; j++) cin >> field[i][j];
    
    for(int by = 0 ; by < H ; by++){
      for(int bx = 0 ; bx < W ; bx++){
	if(field[by][bx] == 1) continue;
	for(int sy = 0 ; sy < H ; sy++){
	  for(int sx = 0 ; sx < W ; sx++){
	    if(sy == by && sx == bx) continue;
	    if(field[sy][sx] == 1) continue;
	    canArrive(bx, by, sx, sy);
	  }
	}
      }
    }

    cout << bfs() << endl;
    
  }

  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1488
final_rank: 3

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

typedef pair<int, int> P;

const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};

int H, W;
int field[8][8];
bool arrive[8][8][8][8][8][8];

void init(){
  memset(field, 0, sizeof(field));
  memset(arrive, false, sizeof(arrive));
}

void canArrive(int bx, int by, int sx, int sy){
  int tmp_field[8][8];
  memset(tmp_field, 0, sizeof(tmp_field));
  for(int i = 0 ; i < H ; i++){
    for(int j = 0 ; j < W ; j++){
      if(field[i][j] != 1) tmp_field[i][j] = 0;
      else tmp_field[i][j] = field[i][j];
    }
  }
  
  tmp_field[by][bx] = 2;

  queue<P> que;
  que.push(P(sx, sy));
  while(!que.empty()){
    P q = que.front(); que.pop();
    arrive[by][bx][sy][sx][q.second][q.first] = true;
    
    for(int i = 0 ; i < 4 ; i++){
      int nx = q.first + dx[i], ny = q.second + dy[i];
      if(nx < 0 || nx >= W || ny < 0 || ny >= H) continue;
      if(tmp_field[ny][nx] != 0) continue;
      if(arrive[by][bx][sy][sx][ny][nx]) continue;
      que.push(P(nx, ny));
    }    
  }
}


struct State{
  int x, y, sx, sy, cost;
  State(int x, int y, int sx, int sy, int cost) : x(x), y(y), sx(sx), sy(sy), cost(cost){}
};

const bool operator < (const State &a, const State &b){
  return a.cost > b.cost;
}

int bfs(){
  int sx, sy, bx, by;
  for(int i = 0 ; i < H ; i++){
    for(int j = 0 ; j < W ; j++){
      if(field[i][j] == 2) bx = j, by = i;
      if(field[i][j] == 4) sx = j, sy = i;
    }
  }
  
  priority_queue<State> que;
  que.push(State(bx, by, sx, sy, 0));
  
  bool used[8][8][8][8];
  memset(used, false, sizeof(used));
  
  while(!que.empty()){
    State p = que.top(); que.pop();

    if(field[p.y][p.x] == 3) return p.cost;    

    if(used[p.y][p.x][p.sy][p.sx]) continue;
    used[p.y][p.x][p.sy][p.sx] = true;
    
    for(int i = 0 ; i < 4 ; i++){
      int nx1, nx2, ny1, ny2;
      nx1 = p.x + dx[i], ny1 = p.y + dy[i];
      nx2 = p.x - dx[i], ny2 = p.y - dy[i];
      if(nx1 < 0 || nx1 >= W || ny1 < 0 || ny1 >= H ||
	 nx2 < 0 || nx2 >= W || ny2 < 0 || ny2 >= H) continue;
      if(field[ny1][nx1] == 1) continue;
      if(field[ny2][nx2] == 1) continue;
      if(!arrive[p.y][p.x][p.sy][p.sx][ny2][nx2]) continue;      
      que.push(State(nx1, ny1, nx2, ny2, p.cost+1));
    }    
  }
  return -1;
}

int main(){
  while(cin >> W >> H, W|H){
    init();
    
    for(int i = 0 ; i < H ; i++)
      for(int j = 0 ; j < W ; j++) cin >> field[i][j];
    
    for(int by = 0 ; by < H ; by++){
      for(int bx = 0 ; bx < W ; bx++){
	if(field[by][bx] == 1) continue;
	for(int sy = 0 ; sy < H ; sy++){
	  for(int sx = 0 ; sx < W ; sx++){
	    if(sy == by && sx == bx) continue;
	    if(field[sy][sx] == 1) continue;
	    canArrive(bx, by, sx, sy);
	  }
	}
      }
    }

    cout << bfs() << endl;
    
  }

  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1492
final_rank: 6

code_snippet: #include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<sstream>
#include<cmath>
using namespace std;
#define REP(i, j) for(int i = 0; i < j; i++)
#define FOR(i, j, k) for(int i = j; i < k; i++)
const int H = 7;
const int W = 7;
const int P = H * W + 10;
const int INF = P * P;

class C{
  public:
    int y, x, cy, cx, s, p;
    C(int _y, int _x, int _cy, int _cx, int _s, int _p){
      y = _y;
      x = _x;
      cy = _cy;
      cx = _cx;
      s = _s;
      p = _p;
    }
    bool operator >(const C c) const{
      return p > c.p;
    }
};

int w, h;

int main(){
  while(cin >>w >>h && w){
    vector< vector<int> > v(h, vector<int>(w));
    int sy, sx, scy, scx;
    REP(i, h){
      REP(j, w){
        cin >>v[i][j];
        if(v[i][j] == 4){
          sy = i;
          sx = j;
          v[i][j] = 0;
        }
        if(v[i][j] == 2){
          scy = i;
          scx = j;
          v[i][j] = 0;
        }
      }
    }

    int ans = -1;
    priority_queue<C, vector<C>, greater<C> > open;
    open.push( C(sy, sx, scy, scx, 0, 0) );
    int closed[P][H][W][H][W];
    REP(i, P) REP(j, H) REP(k, W) REP(l, H) REP(m, W) closed[i][j][k][l][m] = INF;


    while(!open.empty()){
      C now = open.top();
      open.pop();

      //debug
      //cout <<now.y <<" " <<now.x <<" " <<now.cy <<" " <<now.cx <<" " <<now.s <<" " <<now.p <<endl;

      if(v[now.cy][now.cx] == 3){
        ans = now.p;
        break;
      }

      //debug
      //cout <<"step 1" <<endl;
      //cout <<now.s <<" " <<closed[now.p][now.y][now.x][now.cy][now.cx] <<endl;

      if(now.s >= closed[now.p][now.y][now.x][now.cy][now.cx]) continue;
      closed[now.p][now.y][now.x][now.cy][now.cx] = now.s;

      //debug
      //cout <<"step 2" <<endl;

      int my[] = {1, -1, 0, 0};
      int mx[] = {0, 0, 1, -1};
      REP(i, 4){
        int ny = now.y + my[i];
        int nx = now.x + mx[i];
        if(ny < 0 || nx < 0 || ny >= h || nx >= w || v[ny][nx] == 1) continue;
        if(ny == now.cy && nx == now.cx){
          int ncy = ny + my[i];
          int ncx = nx + mx[i];
          if(ncy < 0 || ncx < 0 || ncy >= h || ncx >= w || v[ncy][ncx] == 1) continue;
          open.push( C(ny, nx, ncy, ncx, now.s + 1, now.p + 1) );
        } else{
          open.push( C(ny, nx, now.cy, now.cx, now.s + 1, now.p) );
        }
      }
    }

    cout <<ans <<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1796
final_rank: 4

code_snippet: //42
#include<iostream>
#include<algorithm>

using namespace std;

int main(){
  for(int w,h;cin>>w>>h,w|h;){
    int g[7][7];
    int wx,wy,cx,cy,gx,gy;
    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
	cin>>g[i][j];
	if(g[i][j]==2){
	  cx=j;
	  cy=i;
	}else if(g[i][j]==4){
	  wx=j;
	  wy=i;
	}else if(g[i][j]==3){
	  gx=j;
	  gy=i;
	}
      }
    }
    int d[7][7][7][7];
    fill(d[0][0][0],d[7][0][0],1<<30);
    d[cy][cx][wy][wx]=0;
    for(int i=0;i<w*w*h*h;i++){
      for(int j=0;j<h;j++){
	for(int k=0;k<w;k++){
	  for(int l=0;l<h;l++){
	    for(int m=0;m<w;m++){
	      for(int n=0;n<4;n++){
		int dd[]={0,1,0,-1,0};
		int ny=l+dd[n];
		int nx=m+dd[n+1];
		if(0<=nx&&nx<w&&0<=ny&&ny<h&&g[ny][nx]!=1){
		  if(ny!=j||nx!=k){
		    d[j][k][ny][nx]=min(d[j][k][ny][nx],d[j][k][l][m]);
		  }else{
		    int nny=ny+dd[n];
		    int nnx=nx+dd[n+1];
		    if(0<=nny&&nny<h&&0<=nnx&&nnx<w&&g[nny][nnx]!=1){
		      d[nny][nnx][ny][nx]=min(d[nny][nnx][ny][nx],d[j][k][l][m]+1);
		    }
		  }
		}
	      }
	    }
	  }
	}
      }
    }
    int me=*min_element(d[gy][gx][0],d[gy][gx+1][0]);
    cout<<((me==1<<30)?-1:me)<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 1168
final_rank: 9

code_snippet: #include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

const int dy[]={-1,0,0,1};
const int dx[]={0,-1,1,0};

int main(){

    int w,h;
    int field[20][20];
    while(cin>>w>>h&&!(w==0&&h==0)){
        int gy,gx,sy,sx;
        int mx,my;
        for(int i = 0; i < h; i++){
            for(int j = 0; j < w; j++){
                cin>>field[i][j];
                if(field[i][j]==3){
                    gy=i;
                    gx=j;
                }
                else if(field[i][j]==2){
                    sy=i;
                    sx=j;
                }
                else if(field[i][j]==4){
                    mx=j;
                    my=i;
                }
                if(field[i][j]!=1)
                    field[i][j]=0;
            }
        }
        queue<pair<int,pair<pair<int,int>,pair<int,int> > > > *prv=new queue<pair<int,pair<pair<int,int>,pair<int,int> > > > ();
        queue<pair<int,pair<pair<int,int>,pair<int,int> > > > *nxt=new queue<pair<int,pair<pair<int,int>,pair<int,int> > > > ();
        prv->push(make_pair(0,make_pair(make_pair(sy,sx),make_pair(my,mx))));
        bool passed[100][10][10][10][10];
        memset(passed,0,sizeof(passed));
        passed[0][sy][sx][my][mx]=true;
        int time=0;
        const int INF=1000000000;
        int minTime=INF;
        while(prv->size()){
            while(prv->size()){
                pair<int,int> ccp=prv->front().second.first;
                pair<int,int> cmp=prv->front().second.second;
                int cnt=prv->front().first;
                prv->pop();
                if(ccp.first==gy&&ccp.second==gx)
                    minTime=min(minTime,cnt);
                // lðSÉl¦é
                for(int i = 0; i < 4; i++){
                    int ny=dy[i]+cmp.first;
                    int nx=dx[i]+cmp.second;
                    if(ny>=0&&nx>=0&&nx<w&&ny<h&&field[ny][nx]==0){
                        // »ÌêÉ×¨ª é©Ç¤©
                        if(!(ccp.first==ny&&ccp.second==nx)){
                            if(!passed[cnt][ccp.first][ccp.second][ny][nx]){
                                passed[cnt][ccp.first][ccp.second][ny][nx]=true;
                                nxt->push(make_pair(cnt,make_pair(ccp,make_pair(ny,nx))));
                            }
                        }
                        // ×¨ª éÈçA×¨ð®©¹éêA®©·
                        else{
                            int nccy=ccp.first+dy[i];
                            int nccx=ccp.second+dx[i];
                            if(cnt<99&&nccy>=0&&nccx>=0&&nccy<h&&nccx<w&&field[nccy][nccx]==0){
                                if(!passed[cnt+1][nccy][nccx][ny][nx]){
                                    passed[cnt+1][nccy][nccx][ny][nx]=true;
                                    nxt->push(make_pair(cnt+1,make_pair(make_pair(nccy,nccx),make_pair(ny,nx))));
                                }
                            }
                        }
                    }
                }
            }
            time++;
            swap(prv,nxt);
        }
        if(minTime==INF)cout<<-1<<endl;
        else cout<<minTime<<endl;
        delete prv;
        delete nxt;
    }

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1892
final_rank: 8