Problem:
Problem J:
Infected Land
The earth is under an attack of a deadly virus. Luckily, prompt actions of the Ministry of
Health against this emergency successfully confined the spread of the infection within a square
grid of areas. Recently, public health specialists found an interesting pattern with regard to the
transition of infected areas. At each step in time, every area in the grid changes its infection
state according to infection states of its directly (horizontally, vertically, and diagonally) adjacent
areas.
An infected area continues to be infected if it has two or three adjacent infected areas.
An uninfected area becomes infected if it has exactly three adjacent infected areas.
An area becomes free of the virus, otherwise.
Your mission is to fight against the virus and disinfect all the areas. The Ministry of Health
lets an anti-virus vehicle prototype under your command. The functionality of the vehicle is
summarized as follows.
At the beginning of each time step, you move the vehicle to one of the eight adjacent areas.
      The vehicle is not allowed to move to an infected area (to protect its operators from the
      virus). It is not allowed to stay in the same area.
Following vehicle motion, all the areas, except for the area where the vehicle is in, change
      their infection states according to the transition rules described above.
Special functionality of the vehicle protects its area from virus infection even if the area
      is adjacent to exactly three infected areas. Unfortunately, this virus-protection capability
      of the vehicle does not last. Once the vehicle leaves the area, depending on the infection
      states of the adjacent areas, the area can be infected.
The area where the vehicle is in, which is
uninfected
, has the same effect to its adjacent
      areas as an
infected
area as far as the transition rules are concerned.
The following series of figures illustrate a sample scenario that successfully achieves the goal.
Initially, your vehicle denoted by
@
is found at (1, 5) in a 5 × 5-grid of areas, and you see some
infected areas which are denoted by
#
's.
Firstly, at the beginning of time step 1, you move your vehicle diagonally to the southwest,
that is, to the area (2, 4). Note that this vehicle motion was possible because this area was not
infected at the start of time step 1.
Following this vehicle motion, infection state of each area changes according to the transition
rules. The column "1-end" of the figure illustrates the result of such changes at the end of time
step 1. Note that the area (3, 3) becomes infected because there were two adjacent infected areas
and the vehicle was also in an adjacent area, three areas in total.
In time step 2, you move your vehicle to the west and position it at (2, 3).
Then infection states of other areas change. Note that even if your vehicle had exactly three
infected adjacent areas (west, southwest, and south), the area that is being visited by the vehicle
is
not
in
...(truncated)

Submitted solutions:

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); i++)
const int dx[8] = {1,1,1,-1,-1,-1,0,0};
const int dy[8] = {1,-1,0,1,-1,0,1,-1};
struct data
{
	int mask,x,y;
};
int n;
data next_state(int mask, int x, int y)
{
	int T = 0;
	mask |= (1 << (x*n+y));
	rep(i,n)
		rep(j,n)
		{
			int cnt = 0;
			rep(k,8)
			{
				int xx = i + dx[k];
				int yy = j + dy[k];
				if (xx < 0 || xx >= n || yy < 0 || yy >= n)
					continue;
				if (mask & (1 << (xx*n+yy)))
					cnt++;
			}
			if (mask & (1 << (i * n + j)))
			{
				if (cnt == 3 || cnt == 2)
					T |= 1 << (i * n + j);
			}
			else
			{
				if (cnt == 3)
					T |= 1 << (i*n+j);
			}
		}
	T &= ~(1 << (x * n + y));
	return (data){T, x, y};
}
bool dfs(data s, int dep)
{
	if (s.mask == 0)
		return true;
	if (dep == 0)
		return false;
	rep(i,8)
	{
		int xx = s.x + dx[i];
		int yy = s.y + dy[i];
		if (xx < 0 || xx >= n || yy < 0 || yy >= n) continue;
		if (s.mask & (1 << (xx*n+yy)))
			continue;
		if (dfs(next_state(s.mask,xx,yy),dep-1))
			return true;
	}
	return false;
}
char c[10];
int main()
{
	for (; scanf("%d", &n), n;)
	{
		data s = {};
		rep(i,n)
		{
			scanf("%s", c);
			rep(j,n)
			{
				switch(c[j])
				{
					case '@': s.x = i, s.y = j; break;
					case '#': s.mask |= 1 << (i * n + j);break;
				}
			}
		}
		int ans = -1;
		rep(t,11)
			if (dfs(s, t))
			{
				ans = t;
				break;
			}
		printf("%d\n", ans);
	}
	return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 2920
final_rank: 1

code_snippet: #include <iostream>
#include <cstdio>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

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

struct data1 {
    int S;
    int x,y;
};

int n;

data1 next_state(int S, int x, int y) {
    S |= 1 << (y * n + x);
    int T = 0;
    rep(i, n) rep(j, n) {
        int cnt = 0;
        rep(k, 8) {
            int yy = i + dy[k], xx = j + dx[k];
            if (0 <= yy && yy < n && 0 <= xx && xx < n && (S & (1 << (yy * n + xx)))) cnt++;
        }
        if (S & (1 << (i * n + j))) {
            if (cnt == 2 || cnt == 3) {
                T |= 1 << (i * n + j);
            }
        } else {
            if (cnt == 3) {
                T |= 1 << (i * n + j);
            }
        }
    }
    if (T & (1 << (y * n + x))) T -= (1 << (y * n + x));
    data1 result = {T, x, y};
    return result;
}

bool dfs(data1 D, int t) {
    if (D.S == 0) return true;
    if (t == 0) return false;
    rep(k, 8) {
        int yy = D.y + dy[k], xx = D.x + dx[k];
        if (0 <= yy && yy < n && 0 <= xx && xx < n && (D.S & (1 << (yy * n + xx))) == 0) {
            if (dfs(next_state(D.S, xx, yy), t - 1)) return true;
        }
    }
    return false;
}

int main() {
    while (scanf("%d", &n), n) {
        data1 ini = {0, 0, 0};
        rep(i, n) {
            char s[6]; 
            scanf("%s", s);
            rep(j, n) {
                if (s[j] == '#') ini.S |= 1 << (i * n + j);
                if (s[j] == '@') {
                    ini.x = j; 
                    ini.y = i;
                }
            }
        }

        int ans = -1;
        rep(t, 12) {
            if (dfs(ini, t)) { 
                ans = t; 
                break; 
            }
        }
        printf("%d\n", ans);
    }

    return 0;
}
accuracy: 1
time_ms: 460
memory_kb: 3180
final_rank: 7

code_snippet: #include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <bitset>

using namespace std;

typedef vector<vector<char> > vvchar;

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

int solve(int n, const string *a) {
    vvchar def(n + 2, vector<char>(n + 2));
    vvchar v1(n + 2, vector<char>(n + 2));
    int at = -1;
    int st = 0;
    int bit = 1;

    // Initialize the grid and find the starting positions
    for (int y = 0; y < n; ++y) {
        for (int x = 0; x < n; ++x) {
            if (a[y][x] == '@') {
                at = ((y + 1) << 3) | (x + 1);
            } else if (a[y][x] == '#') {
                v1[y + 1][x + 1] = 1;
                st |= bit;
            }
            bit <<= 1;
        }
    }

    if (st == 0) return 0;

    queue<int> q;
    q.push(st | (at << 25));
    q.push(-1);

    set<int> visit;
    visit.insert(q.front());

    int t = 1;
    while (q.size() > 1) {
        st = q.front();
        q.pop();

        if (st < 0) {
            ++t;
            q.push(-1);
            continue;
        }

        // Reconstruct v1 from the state
        int atx = (st >> 25) & 7;
        int aty = (st >> 28) & 7;
        int mask = 1;
        fill(v1.begin(), v1.end(), vector<char>(n + 2, 0));
        for (int y = 1; y <= n; ++y) {
            for (int x = 1; x <= n; ++x) {
                if (st & mask) {
                    v1[y][x] = 1;
                }
                mask <<= 1;
            }
        }

        for (int i = 0; i < 8; ++i) {
            int ny = aty + dy[i];
            int nx = atx + dx[i];
            if (ny <= 0 || ny > n || nx <= 0 || nx > n) continue;
            if (v1[ny][nx] != 0) continue;

            v1[ny][nx] = 2;
            int nst = 0;
            bit = 1;
            for (int y = 1; y <= n; ++y) {
                for (int x = 1; x <= n; ++x) {
                    int cnt = 0;
                    for (int j = 0; j < 8; ++j) {
                        if (v1[y + dy[j]][x + dx[j]]) {
                            ++cnt;
                        }
                    }
                    if (v1[y][x] == 0) {
                        if (cnt == 3) {
                            nst |= bit;
                        }
                    } else if (v1[y][x] == 1) {
                        if (cnt == 2 || cnt == 3) {
                            nst |= bit;
                        }
                    }
                    bit <<= 1;
                }
            }
            v1[ny][nx] = 0;

            if (nst == 0) return t;

            nst |= (ny << 28) | (nx << 25);
            if (visit.insert(nst).second) {
                q.push(nst);
            }
        }
    }
    return -1;
}

int main() {
    int n;
    string a[5];

    while (cin >> n, n != 0) {
        for (int i = 0; i < n; ++i) {
            cin >> a[i];
        }
        cout << solve(n, a) << '\n';
    }

    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 3372
final_rank: 3

code_snippet: #include <iostream>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <bitset>
using namespace std;

typedef vector<vector<char> > vvchar;

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

int solve(int n, const string *a) {
    vvchar def(n + 2, vector<char>(n + 2));
    vvchar v1 = def;

    int at = -1;
    int st = 0;
    int bit = 1;
    for (int y = 0; y < n; ++y) {
        for (int x = 0; x < n; ++x) {
            if (a[y][x] == '@') {
                at = (y + 1) << 3 | (x + 1);
            } else if (a[y][x] == '#') {
                v1[y + 1][x + 1] = 1;
                st |= bit;
            }

            bit <<= 1;
        }
    }

    if (st == 0) {
        return 0;
    }

    queue<int> q;
    q.push(st | (at << 25));
    q.push(-1);

    set<int> visit;
    visit.insert(q.front());

    int t = 1;
    while (q.size() > 1) {
        st = q.front();
        q.pop();

        if (st < 0) {
            ++t;
            q.push(-1);
        } else {
            v1 = def;
            int atx = (st >> 25) & 7;
            int aty = (st >> 28) & 7;

            int mask = 1;
            for (int y = 1; y <= n; ++y) {
                for (int x = 1; x <= n; ++x) {
                    if (st & mask) {
                        v1[y][x] = 1;
                    }
                    mask <<= 1;
                }
            }

            for (int i = 0; i < 8; ++i) {
                int ny = aty + dy[i];
                int nx = atx + dx[i];
                if (ny <= 0 || ny > n || nx <= 0 || nx > n) {
                    continue;
                }
                if (v1[ny][nx] != 0) {
                    continue;
                }

                v1[ny][nx] = 2;

                int nst = 0;
                bit = 1;
                for (int y = 1; y <= n; ++y)
                for (int x = 1; x <= n; ++x) {
                    int cnt = 0;

                    for (int j = 0; j < 8; ++j) {
                        if (v1[y + dy[j]][x + dx[j]]) {
                            ++cnt;
                        }
                    }

                    if (v1[y][x] == 0) {
                        if (cnt == 3) {
                            nst |= bit;
                        }
                    } else if (v1[y][x] == 1) {
                        if (cnt == 2 || cnt == 3) {
                            nst |= bit;
                        }
                    }

                    bit <<= 1;
                }

                v1[ny][nx] = 0;

                if (nst == 0) {
                    return t;
                }

                nst |= ny << 28 | nx << 25;
                if (visit.insert(nst).second) {
                    q.push(nst);
                }
            }
        }
    }

    return -1;
}

int main() {
    int n;
    string a[5];

    while (cin >> n, n != 0) {
        for (int i = 0; i < n; ++i) {
            cin >> a[i];
        }

        cout << solve(n, a) << '\n';
    }

    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 3352
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <set>
#include <queue>
using namespace std;

struct dat {
    int m, x, y, t;
};

int n;

dat upd(int m, int tx, int ty, int t) {
    dat tm;
    tm.m = 0;
    m |= (1 << (tx * n + ty));
    for (int x = 0;x < n;x++) {
        for (int y = 0;y < n;y++) {
            int cnt = 0;
            for (int i = -1;i <= 1;i++) {
                for (int j = -1;j <= 1;j++) {
                    if (i == 0 && j == 0) continue;
                    int nx = x + i, ny = y + j;
                    if (0 <= nx && 0 <= ny && nx < n && ny < n && (m & (1 << (nx * n + ny)))) {
                        cnt++;
                    }
                }
            }
            if (m & (1 << (n * x + y))) {
                if (cnt == 2 || cnt == 3) tm.m |= (1 << (n * x + y));
            } else if (cnt == 3) tm.m |= (1 << (n * x + y));
        }
    }
    if (tm.m & (1 << (tx * n + ty))) tm.m -= (1 << (tx * n + ty));
    tm.t = t;
    tm.x = tx;
    tm.y = ty;
    return tm;
}

int main() {
    while (true) {
        cin >> n;
        if (!n) break;
        dat s;
        s.m = 0;
        for (int i = 0;i < n;i++) {
            for (int j = 0;j < n;j++) {
                char c; cin >> c;
                if (c == '#') s.m |= (1 << (i * n + j));
                if (c == '@') s.x = i, s.y = j;
            }
        }
        queue<dat> q;
        q.push(s);
        set<vector<int>> st;
        int ans = -1;
        while (!q.empty()) {
            dat v = q.front();
            q.pop();
            if (!v.m) {
                ans = v.t;
                break;
            }
            if (st.find({v.m, v.x, v.y}) != st.end()) continue;
            st.insert({v.m, v.x, v.y});
            for (int i = -1;i <= 1;i++) {
                for (int j = -1;j <= 1;j++) {
                    if (i == 0 && j == 0) continue;
                    int nx = v.x + i, ny = v.y + j;
                    if (0 <= nx && 0 <= ny && nx < n && ny < n && !(v.m & (1 << (nx * n + ny)))) {
                        q.push(upd(v.m, nx, ny, v.t + 1));
                    }
                }
            }
        }
        cout << ans << "\n";
    }
}
accuracy: 1
time_ms: 690
memory_kb: 4060
final_rank: 8

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

using namespace std;

struct S{
  int t;
  vector<char> v;
};

int main(){
  for(int n;cin>>n,n;){
    S is;
    is.t=0;
    is.v.resize(n*n);
    for(int i=0;i<n*n;i++){
      cin>>is.v[i];
    }
    queue<S> que;
    que.push(is);
    set<vector<char> > p;
    while(!que.empty()){
      S c=que.front();
      if(find(c.v.begin(),c.v.end(),'#')==c.v.end())break;
      que.pop();
      if(!p.insert(c.v).second)continue;
      int ps=find(c.v.begin(),c.v.end(),'@')-c.v.begin();
      int x=ps%n;
      int y=ps/n;
      for(int i=-1;i<=1;i++){
	for(int j=-1;j<=1;j++){
	  int nx=x+j;
	  int ny=y+i;
	  if(0<=ny&&ny<n&&0<=nx&&nx<n&&c.v[ny*n+nx]=='.'){
	    vector<char> nv(n*n);
	    for(int k=0;k<n;k++){
	      for(int l=0;l<n;l++){
		if(k==ny&&l==nx){
		  nv[ny*n+nx]='@';
		}else{
		  int ni=0;
		  for(int m=max(0,k-1);m<=min(k+1,n-1);m++){
		    for(int o=max(0,l-1);o<=min(l+1,n-1);o++){
		      ni+=c.v[m*n+o]=='#'||ny==m&&nx==o;
		    }
		  }
		  nv[k*n+l]=((c.v[k*n+l]=='#'&&(ni==3||ni==4))
			     ||(c.v[k*n+l]!='#'&&ni==3))?'#':'.';
		}
	      }
	    }
	    S ns={c.t+1,nv};
	    que.push(ns);
	  }
	}
      }
    }
    cout<<(que.empty()?-1:que.front().t)<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 950
memory_kb: 4860
final_rank: 12

code_snippet: #include <iostream>
#include <cstdio>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

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

struct data1 {
    int S;
    int x,y;
};

int n;

data1 next_state(int S, int x, int y) {
    S |= 1 << (y * n + x);
    int T = 0;
    rep(i, n) rep(j, n) {
        int cnt = 0;
        rep(k, 8) {
            int yy = i + dy[k], xx = j + dx[k];
            if (0 <= yy && yy < n && 0 <= xx && xx < n && (S & (1 << (yy * n + xx)))) cnt++;
        }
        if (S & (1 << (i * n + j))) {
            if (cnt == 2 || cnt == 3) {
                T |= 1 << (i * n + j);
            }
        } else {
            if (cnt == 3) {
                T |= 1 << (i * n + j);
            }
        }
    }
    T &= ~(1 << (y * n + x));
    data1 result = {T, x, y};
    return result;
}

bool dfs(data1 D, int t) {
    if (D.S == 0) return true;
    if (t == 0) return false;
    rep(k, 8) {
        int yy = D.y + dy[k], xx = D.x + dx[k];
        if (0 <= yy && yy < n && 0 <= xx && xx < n && (D.S & (1 << (yy * n + xx))) == 0) {
            if (dfs(next_state(D.S, xx, yy), t - 1)) return true;
        }
    }
    return false;
}

int main() {
    while (scanf("%d", &n), n) {
        data1 ini = {0, 0, 0};
        rep(i, n) {
            char s[6]; 
            scanf("%s", s);
            rep(j, n) {
                if (s[j] == '#') ini.S |= 1 << (i * n + j);
                if (s[j] == '@') {
                    ini.x = j; 
                    ini.y = i;
                }
            }
        }

        int ans = -1;
        rep(t, 11) {
            if (dfs(ini, t)) { 
                ans = t; 
                break; 
            }
        }
        printf("%d\n", ans);
    }

    return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 3168
final_rank: 4

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

using namespace std;

#define FOR(I, A, B) for (int I = int(A); I < int(B); ++I)

const int Q(2000010), N(6);
const int dir[8][2] = {{1, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 0}, {0, 1}, {-1, 0}, {0, -1}};

int n, t, x, y, s;
int q[Q], d[Q];
char str[N][N];
set<int> ha;

int state(int s, int x, int y) {
    return s * 25 + x * 5 + y;
}
void add(int s, int _d) {
    if (ha.count(s)) return;
    d[t] = _d; q[t++] = s; ha.insert(s);
}
int p(int x, int y) {return x * n + y;}
int bit(int x, int y) {
    return (x >> y) & 1;
}
int cnt(int ss, int x, int y) {
    int ret = 0;
    FOR(i, 0, 8) {
        int tx = x + dir[i][0], ty = y + dir[i][1];
        if (tx == -1 || ty == -1 || tx == n || ty == n) continue;
        ret += bit(ss, p(tx, ty));
    }
    return ret;
}
int bfs() {
    if (s == 0) return 0;
    FOR(h, 0, t) {
        y = q[h] % 5; x = q[h] % 25 / 5; s = q[h] / 25;
        FOR(i, 0, 8) {
            int tx = x + dir[i][0], ty = y + dir[i][1];
            if (tx == -1 || ty == -1 || tx == n || ty == n || bit(s, p(tx, ty))) continue;
            int ss = s | (1 << p(tx, ty)), ts = 0;
            FOR(j, 0, n)
                FOR(k, 0, n) {
                    int _cnt = cnt(ss, j, k);
                    if (bit(ss, p(j, k)) == 0) {
                        if (_cnt == 3) ts |= 1 << p(j, k);
                    }
                    else {
                        if (_cnt == 2 || _cnt == 3) ts |= 1 << p(j, k);
                    }
                }
            if (bit(ts, p(tx, ty))) ts -= 1 << p(tx, ty);
            if (ts == 0) return d[h] + 1;
            add(state(ts, tx, ty), d[h] + 1);
        }
    }
    return -1;
}
int main() {
    while (scanf("%d", &n), n) {
        ha.clear();
        FOR(i, 0, n)
            scanf("%s", str[i]);
        t = s = 0;
        FOR(i, 0, n)
            FOR(j, 0, n)
                if (str[i][j] == '@') {
                    x = i; y = j;
                }
                else if (str[i][j] == '#') s |= 1 << p(i, j);
        add(state(s, x, y), 0);
        printf("%d\n", bfs());
    }
    return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 3484
final_rank: 5

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

struct Node {
	int bit, x, y;
	Node(const int bb, const int xx, const int yy) {
		bit = bb, x = xx, y = yy;
	}
	bool operator<(const Node&n)const {
		return make_pair(bit, make_pair(x, y)) < make_pair(n.bit, make_pair(n.x, n.y));
	}
};

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

vector<vector<int>>Field(Node num) {
	vector<vector<int>>field(N, vector<int>(N));
	for (int i = N - 1; i >= 0; i--) {
		for (int j = N - 1; j >= 0; j--) {
			field[i][j] = num.bit&1;
			num.bit >>= 1;
		}
	}
	return field;
}

Node Next(Node num) {
	auto field = Field(num);
//	for (auto i : field) {
//		for (auto j : i)cout << j;
//		cout << endl;
//	}
//	cout << num.y << " " << num.x << endl;
	auto nfield = field;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			if (i == num.y&&j == num.x)continue;
			int cnt = 0;
			for (int k = 0; k < 8; k++) {
				int ny = i + dy[k];
				int nx = j + dx[k];
				if (ny < 0 || nx < 0 || ny >= N || nx >= N)continue;
				cnt += field[ny][nx] || (num.y == ny && num.x == nx);
			}
			if (field[i][j]) {
				if (cnt == 2 || cnt == 3)nfield[i][j] = 1;
				else nfield[i][j] = 0;
			}
			else {
				if (cnt == 3)nfield[i][j] = 1;
				else nfield[i][j] = 0;
			}
		}
	}
//	for (auto i : nfield) {
//		for (auto j : i)cout << j;
//		cout << endl;
//	}
//	cout << num.y << " " << num.x << endl;
	num.bit = 0;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			num.bit <<= 1;
			num.bit += nfield[i][j];
		}
	}
	return num;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	while (cin >> N, N) {
		vector<string>s(N);
		for (auto &i : s)cin >> i;
		int y, x;
		queue<Node>Q;
		int b = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				b <<= 1;
				if (s[i][j] == '@') {
					y = i, x = j;
				}
				b |= s[i][j] == '#';
			}
		}
		Q.push(Node(b, x, y));
		map<Node, int>mp;
		mp[Node(b, x, y)] = 0;
		int ans = -1;
		while (!Q.empty()) {
			auto cn = Q.front();
			Q.pop();
			if (!cn.bit) {
				ans = mp[cn];
				break;
			}
			auto field = Field(cn);
			for (int i = 0; i < 8; i++) {
				int ny = cn.y + dy[i];
				int nx = cn.x + dx[i];
				if (ny < 0 || nx < 0 || ny >= N || nx >= N || field[ny][nx])continue;
				auto nnode = Next(Node(cn.bit, nx, ny));
				if (mp.find(nnode) == mp.end()) {
					mp[nnode] = mp[cn] + 1;
					Q.push(nnode);
				}
			}
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 1810
memory_kb: 4712
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long double EPS = 1e-10;
const long long INF = 1e18;
const long double PI = acos(-1.0L);
//const ll mod = 1000000007;
int N;

vector<string> f(vector<string> S) {
    auto ret = S;
    for(int h = 0; h < N; h++) {
        for(int w = 0; w < N; w++) {
            if(S[h][w] == '@') continue;
            int cnt = 0;
            for(int newh = h - 1; newh <= h + 1; newh++) {
                for(int neww = w-1; neww <= w+1; neww++) {
                    if(newh==h and neww==w) continue;
                    if(newh < 0) continue;
                    if(newh >= N) continue;
                    if(neww < 0) continue;
                    if(neww >= N) continue;
                    if(S[newh][neww] != '.') cnt++;
                }
            }
            if(S[h][w] == '#') {
                if(cnt == 2 or cnt == 3) {
                    ret[h][w] = '#';
                } else {
                    ret[h][w] = '.';
                }
            } else {
                if(cnt == 3) {
                    ret[h][w] = '#';
                } else {
                    ret[h][w] = '.';
                }
            }
        }
    }
    return ret;
}

void print(vector<string> S) {
    for(auto tmp : S) cout << tmp << endl;
}

void solve() {
    vector<string> S(N);
    for(int i = 0; i < N; i++) {
        cin >> S[i];
    }
    map<vector<string>, ll> mp;
    queue<vector<string>> que;
    mp[S] = 0;
    que.push(S);
    while(!que.empty()) {
        auto S = que.front();
        que.pop();
        //cerr << mp[S] << endl;
        //print(S);
        int H, W;
        bool infected = false;
        for(int h = 0; h < N; h++) {
            for(int w = 0; w < N; w++) {
                if(S[h][w] == '@') {
                    H = h;
                    W = w;
                }
                if(S[h][w] == '#') {
                    infected = true;
                }
            }
        }
        if(!infected) {
            cout << mp[S] << endl;
            return;
        }
        for(int h = H - 1; h <= H + 1; h++) {
            for(int w = W - 1; w <= W + 1; w++) {
                if(h == H and w == W) continue;
                if(h < 0) continue;
                if(h >= N) continue;
                if(w < 0) continue;
                if(w >= N) continue;
                if(S[h][w] == '#') continue;
                auto A = S;
                A[H][W] = '.';
                A[h][w] = '@';
                A = f(A);
                if(mp.count(A)) continue;
                mp[A] = mp[S] + 1;
                que.push(A);
            }
        }
    }
    cout << -1 << endl;
}

int main() {
    while(cin >> N) {
        if(N == 0) break;
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 4390
memory_kb: 13632
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
vector<int> dx = {0, 1, 0, -1, 1, -1, -1, 1};
int next(int S, int n){
  int S2 = 0;
  for (int i = 0; i < n; i++){
    for (int j = 0; j < n; j++){
      int cnt = 0;
      for (int k = 0; k < 8; k++){
        int y2 = i + dy[k];
        int x2 = j + dx[k];
        if (0 <= y2 && y2 < n && 0 <= x2 && x2 < n){
          int id = y2 * n + x2;
          if (S >> id & 1){
            cnt++;
          }
        }
      }
      bool flg = false;
      if (S >> (i * n + j) & 1){
        flg = true;
      }
      if (flg && (cnt == 2 || cnt == 3)){
        S2 |= 1 << (i * n + j);
      }
      if (!flg && cnt == 3){
        S2 |= 1 << (i * n + j);
      }
    }
  }
  return S2;
}
int main(){
  while (1){
    int n;
    cin >> n;
    if (n == 0){
      break;
    }
    vector<vector<char>> a(n, vector<char>(n));
    for (int i = 0; i < n; i++){
      for (int j = 0; j < n; j++){
        cin >> a[i][j];
      }
    }
    int S = 0;
    int p = 0;
    for (int i = 0; i < n; i++){
      for (int j = 0; j < n; j++){
        if (a[i][j] == '@'){
          p = i * n + j;
        }
        if (a[i][j] == '#'){
          S += 1 << (i * n + j);
        }
      }
    }
    set<pair<int, int>> used;
    used.insert(make_pair(S, p));
    int ans = -1;
    queue<tuple<int, int, int>> Q;
    Q.push(make_tuple(0, S, p));
    while (!Q.empty()){
      int d = get<0>(Q.front());
      int s = get<1>(Q.front());
      int c = get<2>(Q.front());
      Q.pop();
      if (s == 0){
        ans = d;
        break;
      }
      int y = c / n;
      int x = c % n;
      for (int i = 0; i < 8; i++){
        int y2 = y + dy[i];
        int x2 = x + dx[i];
        if (0 <= y2 && y2 < n && 0 <= x2 && x2 < n){
          int c2 = y2 * n + x2;
          if (!(s >> c2 & 1)){
            int s2 = s | (1 << c2);
            s2 = next(s2, n);
            s2 &= ~(1 << c2);
            if (!used.count(make_pair(s2, c2))){
              used.insert(make_pair(s2, c2));
              Q.push(make_tuple(d + 1, s2, c2));
            }
          }
        }
      }
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 670
memory_kb: 4656
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=105,INF=1<<27;
map<pair<int,int>,int> MA;
int N;

void BFS(int bit,int s){
    queue<pair<int,int>> Q;
    Q.push(mp(bit,s));
    MA[mp(bit,s)]=0;
    
    while(!Q.empty()){
        auto u=Q.front();Q.pop();
        int h=u.se/N,w=u.se%N;
        int bi=u.fi;
        
        bool check=false;
        
        for(int dh=-1;dh<=1;dh++){
            for(int dw=-1;dw<=1;dw++){
                if(dh==0&&dw==0) continue;
                if(h+dh<0||h+dh>=N||w+dw<0||w+dw>=N) continue;
                if(bi&(1<<((h+dh)*N+(w+dw)))) continue;
                
                pair<int,int> to;
                to.se=(h+dh)*N+(w+dw);
                
                bi+=(1<<to.se);
                
                for(int i=0;i<N;i++){
                    for(int j=0;j<N;j++){
                        if(i*N+j==to.se) continue;
                        int cnt=0;
                        for(int ddh=-1;ddh<=1;ddh++){
                            for(int ddw=-1;ddw<=1;ddw++){
                                if(ddh==0&&ddw==0) continue;
                                if(i+ddh<0||i+ddh>=N||j+ddw<0||j+ddw>=N) continue;
                                
                                if(bi&(1<<((i+ddh)*N+(j+ddw)))) cnt++;
                            }
                        }
                        if(bi&(1<<(i*N+j))){
                            if(cnt==2||cnt==3) to.fi+=(1<<(i*N+j));
                        }else{
                            if(cnt==3) to.fi+=(1<<(i*N+j));
                        }
                    }
                }
                
                bi-=(1<<to.se);
                
                if(MA.count(to)==0){
                    MA[to]=MA[u]+1;
                    Q.push(to);
                }
                
                if(to.fi==0) check=true;
            }
        }
        
        if(check) break;
    }
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        cin>>N;
        if(N==0) break;
        MA.clear();
        
        int s=0,bit=0;
        
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                char c;cin>>c;
                if(c=='@') s=i*N+j;
                if(c=='#') bit+=1<<(i*N+j);
            }
        }
        
        BFS(bit,s);
        
        int ans=INF;
        
        for(int i=0;i<N*N;i++) if(MA.count(mp(0,i))) chmin(ans,MA[mp(0,i)]);
        
        if(ans==INF) ans=-1;
        
        cout<<ans<<endl;
    }
}
accuracy: 1
time_ms: 210
memory_kb: 3572
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i, n) for (int i=0; i<(n); ++i)
#define RREP(i, n) for (int i=(int)(n)-1; i>=0; --i)
#define FOR(i, a, n) for (int i=(a); i<(n); ++i)
#define RFOR(i, a, n) for (int i=(int)(n)-1; i>=(a); --i)

#define SZ(x) ((int)(x).size())
#define all(x) begin(x),end(x)

#define dump(x) cerr<<#x<<" = "<<(x)<<endl
#define debug(x) cerr<<#x<<" = "<<(x)<<" (L"<<__LINE__<<")"<<endl;

template<class T>
ostream &operator<<(ostream &os, const vector <T> &v) {
    os << "[";
    REP(i, SZ(v)) {
        if (i) os << ", ";
        os << v[i];
    }
    return os << "]";
}

template<class T, class U>
ostream &operator<<(ostream &os, const pair <T, U> &p) {
    return os << "(" << p.first << " " << p.second << ")";
}

template<class T>
bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
bool chmin(T &a, const T &b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using P = pair<int, int>;
using vi = vector<int>;
using vll = vector<ll>;
using vvi = vector<vi>;
using vvll = vector<vll>;

const ll MOD = 1e9 + 7;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;
const ld eps = 1e-9;


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);

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

    for (;;) {
        int n; cin >> n;
        if (n == 0) break;

        string a;
        int si, sj;
        REP(i, n) {
            string s; cin >> s;
            a += s;
            REP(j, n) {
                if (s[j] == '@') {
                    si = i, sj = j;
                }
            }
        }

        queue<tuple<string,int,int>> que;
        map<tuple<string,int,int>,int> dist;
        que.emplace(a, si, sj);
        dist[make_tuple(a, si, sj)] = 0;

        int ans = -1;

        while (!que.empty()) {
            string board;
            int si, sj;
            int d = dist[que.front()];
            tie(board, si, sj) = que.front();
            que.pop();

            bool finish = true;
            REP(i, n*n) {
                if (board[i] == '#') {
                    finish = false;
                    break;
                }
            }
            if (finish) {
                ans = d;
                break;
            }

            REP(k, 8) {
                string tmp = board;
                int y = si + dy[k], x = sj + dx[k];
                if (y < 0 or x < 0 or n <= y or n <= x or
                    tmp[y*n + x] == '#') continue;
                tmp[y*n + x] = '@';
                tmp[si*n + sj] = '.';
                string nxt;
                REP(i, n) {
                    REP(j, n) {
                        if (i == y and j == x) {
                            nxt += '@';
                            continue;
                        }
                        int cnt = 0;
                        REP(t, 8) {
                            int y = i + dy[t], x = j + dx[t];
                            if (y < 0 or x < 0 or n <= y or n <= x) continue;
                            cnt += tmp[y*n + x] != '.';
                        }
                        if (tmp[i*n + j] == '#' and (cnt == 2 or cnt == 3)) {
                            nxt += '#';
                        } else if (tmp[i*n + j] == '.' and cnt == 3) {
                            nxt += '#';
                        } else {
                            nxt += '.';
                        }
                    }
                }
                if (dist.count(make_tuple(nxt, y, x)) == 0) {
                    dist[make_tuple(nxt, y, x)] = d + 1;
                    que.emplace(nxt, y, x);
                } else if (chmin(dist[make_tuple(nxt, y, x)], d + 1)){
                    que.emplace(nxt, y, x);
                }
            }
        }

        cout << ans << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 1990
memory_kb: 7080
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;
const double eps = 1e-8;
const ll MOD = 1000000007;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;
template<typename T1, typename T2>
void chmax(T1 &a, const T2 &b) {
  if (a < b) a = b;
}
template<typename T1, typename T2>
void chmin(T1 &a, const T2 &b) {
  if (a > b) a = b;
}
template<typename T>
void printv(const vector<T> &s) {
  for (int i = 0; i < (int) (s.size()); ++i) {
    cout << s[i];
    if (i != (int) (s.size()) - 1) cout << " ";
  }
  cout << "\n";
}
template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> p) {
  os << p.first << ":" << p.second;
  return os;
}
struct RollingHash {
  const int base = 9973;
  const int mod[2] = {999999937, 1000000007};
  vector<int> s;
  vector<ll> hash[2], pow[2];
  template<class S>
  RollingHash(const S &s) {
    int n = s.size();
    for (int id = 0; id < 2; ++id) {
      hash[id].assign(n+1, 0);
      pow[id].assign(n+1, 1);
      for (int i = 0; i < n; ++i) {
        hash[id][i+1] = (hash[id][i] * base + s[i]) % mod[id];
        pow[id][i+1] = pow[id][i] * base % mod[id];
      }
    }
  }
  pair<ll,ll> get(int l, int r) {
    ll ret[2];
    for (int id = 0; id < 2; ++id) {
      ret[id] = hash[id][r] - hash[id][l] * pow[id][r - l] % mod[id];
      if (ret[id] < 0) ret[id] += mod[id];
    }
    return { ret[0], ret[1] };
  }
};
struct Elm {
  int d, r, c;
  ll hash;
  vector<string> v;
};
bool operator<(const Elm &e1, const Elm &e2) {
  return e1.d > e2.d;
}
bool solve() {
  int n;
  cin >> n;
  if (n == 0) return false;
  vector<string> in(n);
  int r = -1, c = -1;
  int cnt = 0;
  for(int i=0;i<n;++i) {
    cin >> in[i];
    for(int j=0;j<n;++j) {
      if (in[i][j] == '@') r = i, c = j;
      cnt += in[i][j] == '#';
    }
  }
  if(cnt == 0) {
    cout << 0 << endl;
    return true;
  }
  map<ll, int> mp;
  queue<Elm> pq;
  ll hash = 0;
  ll now = 1;
  for(int i=0;i<n;++i) {
    for(int j=0;j<n;++j) {
      hash += now * in[i][j];
      hash %= MOD;
      now *= 998244353;
      now %= MOD;
    }
  }
  mp[hash] = 0;
  pq.push({0, r, c, hash, in});
  vi dr = {-1, 1, 0, 0}, dc = {0, 0, -1, 1};
  vi dr2 = {1, 1, 0, -1, -1, -1, 0, 1}, dc2 = {0, -1, -1, -1, 0, 1, 1, 1};
  ll ans = -1;
  while (!pq.empty()) {
    auto now = pq.front();
    pq.pop();
    int d = now.d, r = now.r, c = now.c;
    ll hash = now.hash;
    auto v = now.v;
    if (mp.find(hash) != mp.end() && mp[hash] < d) continue;
    for(int i=0;i<8;++i) {
      if(ans != -1) break;
      vector<string> nxt(n);
      for(int j=0;j<n;++j) {
        nxt[j].assign(n, '.');
      }
      int nr = r + dr2[i], nc = c + dc2[i];
      if (!(0 <= nr && nr < n && 0 <= nc && nc < n) || v[nr][nc] == '#') continue;
      nxt[nr][nc] = '@';
      int cnt_sharp = 0;
      for(int j=0;j<n;++j) {
        for(int k=0;k<n;++k) {
          int cnt = 0;
          for(int l=0;l<8;++l) {
            int adjr = j + dr2[l], adjc = k + dc2[l];
            if (0 <= adjr && adjr < n && 0 <= adjc && adjc < n) {
              cnt += v[adjr][adjc] == '#' || nxt[adjr][adjc] == '@';
            }
          }
          if ((v[j][k] == '#' && (cnt == 2 || cnt == 3)) ||
              ((v[j][k] == '.' || v[j][k] == '@') && nxt[j][k] != '@' && cnt == 3)) {
            nxt[j][k] = '#';
            cnt_sharp++;
          }
        }
      }
      ll nxthash = 0;
      ll nowmul = 1;
      for(int i=0;i<n;++i) {
        for(int j=0;j<n;++j) {
          nxthash += nowmul * nxt[i][j];
          nxthash %= MOD;
          nowmul *= 998244353;
          nowmul %= MOD;
        }
      }
      if (mp.find(nxthash) == mp.end() || mp[nxthash] > d + 1) {
        if(cnt_sharp == 0) {
          ans = d+1;
          break;
        }
        mp[nxthash] = d + 1;
        pq.push({d + 1, nr, nc, nxthash, nxt});
      }
    }
  }
  cout << (ans == LINF ? -1 : ans) << endl;
  return true;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);
  while (1) {
    if (!solve()) break;
  }
}
accuracy: 1
time_ms: 700
memory_kb: 4536
final_rank: 9

code_snippet: #define  _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES

#pragma comment (linker, "/STACK:526000000")

#include "bits/stdc++.h"

using namespace std;
typedef string::const_iterator State;
#define eps 1e-5L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
#define REP(a,b) for(long long (a) = 0;(a) < (b);++(a))
#define ALL(x) (x).begin(),(x).end()

// geometry library

typedef complex<long double> Point;
typedef pair<complex<long double>, complex<long double>> Line;

typedef struct Circle {
    complex<long double> center;
    long double r;
}Circle;

long double dot(Point a, Point b) {
    return (a.real() * b.real() + a.imag() * b.imag());
}
long double cross(Point a, Point b) {
    return (a.real() * b.imag() - a.imag() * b.real());
}

long double Dist_Line_Point(Line a, Point b) {
    if (dot(a.second - a.first, b - a.first) < eps) return abs(b - a.first);
    if (dot(a.first - a.second, b - a.second) < eps) return abs(b - a.second);
    return abs(cross(a.second - a.first, b - a.first)) / abs(a.second - a.first);
}

int is_intersected_ls(Line a, Line b) {
    return (cross(a.second - a.first, b.first - a.first) * cross(a.second - a.first, b.second - a.first) < eps) &&
        (cross(b.second - b.first, a.first - b.first) * cross(b.second - b.first, a.second - b.first) < eps);
}

Point intersection_l(Line a, Line b) {
    Point da = a.second - a.first;
    Point db = b.second - b.first;
    return a.first + da * cross(db, b.first - a.first) / cross(db, da);
}

long double Dist_Line_Line(Line a, Line b) {
    if (is_intersected_ls(a, b) == 1) {
        return 0;
    }
    return min({ Dist_Line_Point(a,b.first), Dist_Line_Point(a,b.second),Dist_Line_Point(b,a.first),Dist_Line_Point(b,a.second) });
}

pair<Point, Point> intersection_Circle_Circle(Circle a, Circle b) {
    long double dist = abs(a.center - b.center);
    assert(dist <= eps + a.r + b.r);
    assert(dist + eps >= abs(a.r - b.r));
    Point target = b.center - a.center;
    long double pointer = target.real() * target.real() + target.imag() * target.imag();
    long double aa = pointer + a.r * a.r - b.r * b.r;
    aa /= 2.0L;
    Point l{ (aa * target.real() + target.imag() * sqrt(pointer * a.r * a.r - aa * aa)) / pointer,
            (aa * target.imag() - target.real() * sqrt(pointer * a.r * a.r - aa * aa)) / pointer };
    Point r{ (aa * target.real() - target.imag() * sqrt(pointer * a.r * a.r - aa * aa)) / pointer,
        (aa * target.imag() + target.real() * sqrt(pointer * a.r * a.r - aa * aa)) / pointer };
    r = r + a.center;
    l = l + a.center;
    return mp(l, r);
}

//end of geometry

template<typename A>
A pows(A val, ll b) {
    assert(b >= 1);
    A ans = val;
    b--;
    while (b) {
        if (b % 2) {
            ans *= val;
        }
        val *= val;
        b /= 2LL;
    }
    return ans;
}

template<typename A>
class Compressor {
public:
    bool is_zipped = false;
    map<A, ll> zipper;
    map<ll, A> unzipper;
    queue<A> fetcher;
    Compressor() {
        is_zipped = false;
        zipper.clear();
        unzipper.clear();
    }
    void add(A now) {
        assert(is_zipped == false);
        zipper[now] = 1;
        fetcher.push(now);
    }
    void exec() {
        assert(is_zipped == false);
        int cnt = 0;
        for (auto i = zipper.begin(); i != zipper.end(); ++i) {
            i->second = cnt;
            unzipper[cnt] = i->first;
            cnt++;
        }
        is_zipped = true;
    }
    ll fetch() {
        assert(is_zipped == true);
        A hoge = fetcher.front();
        fetcher.pop();
        return zipper[hoge];
    }
    ll zip(A now) {
        assert(is_zipped == true);
        assert(zipper.find(now) != zipper.end());
        return zipper[now];
    }
    A unzip(ll a) {
        assert(is_zipped == true);
        assert(a < unzipper.size());
        return unzipper[a];
    }
    ll next(A now) {
        auto x = zipper.upper_bound(now);
        if (x == zipper.end()) return zipper.size();
        return (ll)((*x).second);
    }
    ll back(A now) {
        auto x = zipper.lower_bound(now);
        if (x == zipper.begin()) return -1;
        x--;
        return (ll)((*x).second);
    }
};

template<typename A>
class Matrix {
public:
    vector<vector<A>> data;
    Matrix(vector<vector<A>> a) :data(a) {

    }
    Matrix operator + (const Matrix obj) {
        vector<vector<A>> ans;
        assert(obj.data.size() == this->data.size());
        assert(obj.data[0].size() == this->data[0].size());
        REP(i, obj.data.size()) {
            ans.push_back(vector<A>());
            REP(q, obj.data[i].size()) {
                A hoge = obj.data[i][q] + (this->data[i][q]);
                ans.back().push_back(hoge);
            }
        }
        return Matrix(ans);
    }
    Matrix operator - (const Matrix obj) {
        vector<vector<A>> ans;
        assert(obj.data.size() == this->data.size());
        assert(obj.data[0].size() == this->data[0].size());
        REP(i, obj.data.size()) {
            ans.push_back(vector<A>());
            REP(q, obj.data[i].size()) {
                A hoge = this->data[i][q] - obj.data[i][q];
                ans.back().push_back(hoge);
            }
        }
        return Matrix(ans);
    }
    Matrix operator * (const Matrix obj) {
        vector<vector<A>> ans;
        assert(obj.data.size() == this->data[0].size());
        REP(i, this -> data.size()) {
            ans.push_back(vector<A>());
            REP(q, obj.data[0].size()) {
                A hoge = (this->data[i][0]) * (obj.data[0][q]);
                for (int t = 1; t < obj.data[i].size(); ++t) {
                    hoge += this->data[i][t] * obj.data[t][q];
                }
                ans.back().push_back(hoge);
            }
        }
        return Matrix(ans);
    }
    Matrix& operator *= (const Matrix obj) {
        *this = (*this * obj);
        return *this;
    }
    Matrix& operator += (const Matrix obj) {
        *this = (*this + obj);
        return *this;
    }
    Matrix& operator -= (const Matrix obj) {
        *this = (*this - obj);
        return *this;
    }
};

class modint {
public:
    using u64 = std::uint_fast64_t;
    u64 value = 0;
    u64 mod;
    modint(ll a, ll b) : value(((a% b) + 2 * b) % b), mod(b) {

    }
    modint operator+(const modint rhs) const {
        return modint(*this) += rhs;
    }
    modint operator-(const modint rhs) const {
        return modint(*this) -= rhs;
    }
    modint operator*(const modint rhs) const {
        return modint(*this) *= rhs;
    }
    modint operator/(const modint rhs) const {
        return modint(*this) /= rhs;
    }
    modint& operator+=(const modint rhs) {
        assert(rhs.mod == mod);
        value += rhs.value;
        if (value >= mod) {
            value -= mod;
        }
        return *this;
    }
    modint& operator-=(const modint rhs) {
        assert(rhs.mod == mod);
        if (value < rhs.value) {
            value += mod;
        }
        value -= rhs.value;
        return *this;
    }
    modint& operator*=(const modint rhs) {
        assert(rhs.mod == mod);
        value = (value * rhs.value) % mod;
        return *this;
    }
    modint& operator/=(modint rhs) {
        assert(rhs.mod == mod);
        ll rem = mod - 2;
        while (rem) {
            if (rem % 2) {
                *this *= rhs;
            }
            rhs *= rhs;
            rem /= 2LL;
        }
        return *this;
    }
    bool operator <(modint rhs) const {
        return value < rhs.value;
    }
    friend ostream& operator<<(ostream& os, modint& p) {
        os << p.value;
        return (os);
    }
};

class Dice {
public:
    vector<ll> vertexs;
    //Up: 0,Left: 1,Center: 2,Right: 3,Adj: 4, Down: 5
    Dice(vector<ll> init) :vertexs(init) {

    }
    //Look from Center
    void RtoL() {
        for (int q = 1; q < 4; ++q) {
            swap(vertexs[q], vertexs[q + 1]);
        }
    }
    void LtoR() {
        for (int q = 3; q >= 1; --q) {
            swap(vertexs[q], vertexs[q + 1]);
        }
    }
    void UtoD() {
        swap(vertexs[5], vertexs[4]);
        swap(vertexs[2], vertexs[5]);
        swap(vertexs[0], vertexs[2]);
    }
    void DtoU() {
        swap(vertexs[0], vertexs[2]);
        swap(vertexs[2], vertexs[5]);
        swap(vertexs[5], vertexs[4]);
    }
    bool ReachAble(Dice now) {
        set<Dice> hoge;
        queue<Dice> next;
        next.push(now);
        hoge.insert(now);
        while (next.empty() == false) {
            Dice seeing = next.front();
            next.pop();
            if (seeing == *this) return true;
            seeing.RtoL();
            if (hoge.count(seeing) == 0) {
                hoge.insert(seeing);
                next.push(seeing);
            }
            seeing.LtoR();
            seeing.LtoR();
            if (hoge.count(seeing) == 0) {
                hoge.insert(seeing);
                next.push(seeing);
            }
            seeing.RtoL();
            seeing.UtoD();
            if (hoge.count(seeing) == 0) {
                hoge.insert(seeing);
                next.push(seeing);
            }
            seeing.DtoU();
            seeing.DtoU();
            if (hoge.count(seeing) == 0) {
                hoge.insert(seeing);
                next.push(seeing);
            }
        }
        return false;
    }
    bool operator ==(const Dice& a) {
        for (int q = 0; q < 6; ++q) {
            if (a.vertexs[q] != (*this).vertexs[q]) {
                return false;
            }
        }
        return true;
    }
    bool operator <(const Dice& a) const {
        return (*this).vertexs < a.vertexs;
    }
};

pair<Dice, Dice> TwoDimDice(int center, int up) {
    int target = 1;
    while (true) {
        if (center != target && 7 - center != target && up != target && 7 - up != target) {
            break;
        }
        target++;
    }
    return mp(Dice(vector<ll>{up, target, center, 7 - target, 7 - center, 7 - up}), Dice(vector<ll>{up, 7 - target, center, target, 7 - center, 7 - up}));
}

tuple<Dice, Dice, Dice, Dice> OneDimDice(int center) {
    int bo = min(center, 7 - center);
    pair<int, int> goa;
    if (bo == 1) {
        goa = mp(2, 3);
    }
    else if (bo == 2) {
        goa = mp(1, 3);
    }
    else if (bo == 3) {
        goa = mp(1, 2);
    }
    tuple<Dice, Dice, Dice, Dice> now = make_tuple(Dice(vector<ll>{goa.first, goa.second, center, 7 - goa.second, 7 - center, 7 - goa.first}),
        Dice(vector<ll>{goa.first, 7 - goa.second, center, goa.second, 7 - center, 7 - goa.first}),
        Dice(vector<ll>{7 - goa.first, goa.second, center, 7 - goa.second, 7 - center, goa.first}),
        Dice(vector<ll>{7 - goa.first, 7 - goa.second, center, goa.second, 7 - center, goa.first}));
    return now;
}

template<typename A, typename B>
class Dijkstra {
public:
    vector<vector<pair<int, A>>> vertexs;
    B Cost_Function;
    Dijkstra(int n, B cost) : Cost_Function(cost) {
        vertexs = vector<vector<pair<int, A>>>(n, vector<pair<int, A>>{});
    }
    ~Dijkstra() {
        vertexs.clear();
    }
    void add_edge(int a, int b, A c) {
        vertexs[a].push_back(mp(b, c));
    }
    vector<ll> build_result(int StartPoint) {
        vector<ll> dist(vertexs.size(), 2e18);
        dist[StartPoint] = 0;
        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> next;
        next.push(make_pair(0, StartPoint));
        while (next.empty() == false) {
            pair<ll, int> now = next.top();
            next.pop();
            if (dist[now.second] != now.first) continue;
            for (auto x : vertexs[now.second]) {
                ll now_cost = now.first + Cost_Function(x.second);
                if (dist[x.first] > now_cost) {
                    dist[x.first] = now_cost;
                    next.push(mp(now_cost, x.first));
                }
            }
        }
        return dist;
    }
};

class Dinic {
public:
    struct edge {
        int to;
        int cap;
        int rev;
    };
    vector<vector<edge>> Graph;
    vector<int> level;
    vector<int> itr;
    Dinic(int n) {
        Graph = vector<vector<edge>>(n, vector<edge>());
    }
    void add_edge(int a, int b, int cap) {
        Graph[a].push_back(edge{ b, cap ,(int)Graph[b].size() });
        Graph[b].push_back(edge{ a,0,(int)Graph[a].size() - 1 });
    }
    void bfs(int s) {
        level = vector<int>(Graph.size(), -1);
        level[s] = 0;
        queue<int> next;
        next.push(s);
        while (next.empty() == false) {
            int now = next.front();
            next.pop();
            for (auto x : Graph[now]) {
                if (x.cap == 0) continue;
                if (level[x.to] == -1) {
                    level[x.to] = level[now] + 1;
                    next.push(x.to);
                }
            }
        }
    }
    int dfs(int now, int goal, int val) {
        if (goal == now) return val;
        for (int& i = itr[now]; i < (int)Graph[now].size(); ++i) {
            edge& target = Graph[now][i];
            if (target.cap > 0 && level[now] < level[target.to]) {
                int d = dfs(target.to, goal, min(val, target.cap));
                if (d > 0) {
                    target.cap -= d;
                    Graph[target.to][target.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
    int run(int s, int t) {
        int ans = 0;
        int f = 0;
        while (bfs(s), level[t] >= 0) {
            itr = vector<int>(Graph.size(), 0);
            while ((f = dfs(s, t, 1e9)) > 0) {
                ans += f;
            }
        }
        return ans;
    }
};

//by ei1333
//https://ei1333.github.io/luzhiled/snippets/structure/segment-tree.html
template< typename Monoid >
struct SegmentTree {
    using F = function< Monoid(Monoid, Monoid) >;

    int sz;
    vector< Monoid > seg;

    const F f;
    const Monoid M1;

    SegmentTree(int n, const F f, const Monoid& M1) : f(f), M1(M1) {
        sz = 1;
        while (sz < n) sz <<= 1;
        seg.assign(2 * sz + 1, M1);
    }

    void set(int k, const Monoid& x) {
        seg[k + sz] = x;
    }

    void build() {
        for (int k = sz - 1; k > 0; k--) {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }

    void update(int k, const Monoid& x) {
        k += sz;
        seg[k] = x;
        while (k >>= 1) {
            seg[k] = f(seg[2 * k + 0], seg[2 * k + 1]);
        }
    }

    Monoid query(int a, int b) {
        Monoid L = M1, R = M1;
        for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
            if (a & 1) L = f(L, seg[a++]);
            if (b & 1) R = f(seg[--b], R);
        }
        return f(L, R);
    }

    Monoid operator[](const int& k) const {
        return seg[k + sz];
    }

    template< typename C >
    int find_subtree(int a, const C& check, Monoid& M, bool type) {
        while (a < sz) {
            Monoid nxt = type ? f(seg[2 * a + type], M) : f(M, seg[2 * a + type]);
            if (check(nxt)) a = 2 * a + type;
            else M = nxt, a = 2 * a + 1 - type;
        }
        return a - sz;
    }


    template< typename C >
    int find_first(int a, const C& check) {
        Monoid L = M1;
        if (a <= 0) {
            if (check(f(L, seg[1]))) return find_subtree(1, check, L, false);
            return -1;
        }
        int b = sz;
        for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
            if (a & 1) {
                Monoid nxt = f(L, seg[a]);
                if (check(nxt)) return find_subtree(a, check, L, false);
                L = nxt;
                ++a;
            }
        }
        return -1;
    }

    template< typename C >
    int find_last(int b, const C& check) {
        Monoid R = M1;
        if (b >= sz) {
            if (check(f(seg[1], R))) return find_subtree(1, check, R, true);
            return -1;
        }
        int a = sz;
        for (b += sz; a < b; a >>= 1, b >>= 1) {
            if (b & 1) {
                Monoid nxt = f(seg[--b], R);
                if (check(nxt)) return find_subtree(b, check, R, true);
                R = nxt;
            }
        }
        return -1;
    }
};

unsigned long xor128() {
    static unsigned long x = 123456789, y = 362436069, z = 521288629, w = 88675123;
    unsigned long t = (x ^ (x << 11));
    x = y; y = z; z = w;
    return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}

void init() {
    iostream::sync_with_stdio(false);
    cout << fixed << setprecision(20);
}

#define int long long

void solve() {
    while (true) {
        int n;
        cin >> n;
        if (n == 0)return;
        int cnt = 0;
        REP(i, n) {
            string s;
            cin >> s;
            REP(q, n) {
                if (s[q] == '#') {
                    cnt += (1 << (i * n + q + 5));
                }
                else if (s[q] == '@') {
                    cnt += i * n + q;
                }
            }
        }
        set<int> gogo;
        gogo.insert(cnt);
        queue<pair<int, int>> next;
        next.push(mp(cnt, 0));
        int ans = -1;
        while (next.empty() == false) {
            pair<int, int> now = next.front();
            next.pop();
            int grid[5][5] = {};
            int cnt = 0;
            REP(i, n) {
                REP(q, n) {
                    if ((1LL << (i * n + q + 5)) & now.first) {
                        grid[i][q] = 1;
                        cnt++;
                    }
                }
            }
            if (cnt == 0) {
                ans = now.second;
                break;
            }
            const int dx[8] = { 1,1,1,0,0,-1,-1,-1 };
            const int dy[8] = { 1,0,-1,1,-1,1,0,-1 };
            pair<int, int> place = mp((now.first % (1 << 5)) / n, (now.first % (1 << 5)) % n);
            REP(q, 8) {
                int x = place.first + dx[q];
                int y = place.second + dy[q];
                if (x >= 0 && x < n && y >= 0 && y < n&&grid[x][y]  == 0) {
                    grid[x][y] = 1;
                    int tmp = x * n + y;
                    REP(j, n) {
                        REP(t, n) {
                            if (j == x && t == y) continue;
                            int cnter = 0;
                            REP(p, 8) {
                                int next_x = j + dx[p];
                                int next_y = t + dy[p];
                                if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < n) {
                                    cnter += grid[next_x][next_y];
                                }
                            }
                            int doing = 0;
                            if (grid[j][t] == 1) {
                                if (cnter >= 2 && cnter <= 3) {
                                    doing = 1;
                                }
                            }
                            else {
                                if (cnter == 3) {
                                    doing = 1;
                                }
                            }
                            tmp += doing * (1LL << (5 + j * n + t));
                        }
                    }
                    if (gogo.count(tmp) == 0) {
                        gogo.insert(tmp);
                        next.push(mp(tmp, now.second + 1));
                    }
                    grid[x][y] = 0;
                }
            }
        }
        cout << ans << endl;
    }
}
#undef int
int main() {
    init();
    solve();
}
accuracy: 1
time_ms: 750
memory_kb: 4540
final_rank: 11

code_snippet: #include<iostream>
#include<queue>
#include<map>
using namespace std;
int N;
int dx[8]={0,1,0,-1,1,1,-1,-1};
int dy[8]={1,0,-1,0,1,-1,1,-1};
main()
{
	while(cin>>N,N)
	{
		string start="";
		for(int i=0;i<N;i++)
		{
			string input;cin>>input;start+=input;
		}
		map<string,int>M;
		M[start]=0;
		queue<string>P;
		P.push(start);
		int ans=-1;
		while(!P.empty())
		{
			string now=P.front();P.pop();
			int cost=M[now];
			int sx,sy;
			int cnt=0;
			for(int i=0;i<N*N;i++)
			{
				if(now[i]=='@')sx=i/N,sy=i%N;
				if(now[i]=='#')cnt++;
			}
			if(cnt==0)
			{
				ans=cost;
				break;
			}
			for(int r=0;r<8;r++)
			{
				int tx=sx+dx[r],ty=sy+dy[r];
				if(tx<0||ty<0||tx>=N||ty>=N||now[tx*N+ty]=='#')continue;
				string tmp=now;
				tmp[sx*N+sy]='.';
				tmp[tx*N+ty]='@';
				string nxt=tmp;
				for(int x=0;x<N;x++)for(int y=0;y<N;y++)
				{
					if(nxt[x*N+y]=='@')continue;
					int cnt=0;
					for(int r=0;r<8;r++)
					{
						int xx=x+dx[r],yy=y+dy[r];
						if(0<=xx&&xx<N&&0<=yy&&yy<N&&tmp[xx*N+yy]!='.')cnt++;
					}
					if(tmp[x*N+y]=='#'?2<=cnt&&cnt<=3:cnt==3)nxt[x*N+y]='#';
					else nxt[x*N+y]='.';
				}
				if(M.find(nxt)==M.end())
				{
					M[nxt]=cost+1;
					P.push(nxt);
				}
			}
		}
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 1590
memory_kb: 7184
final_rank: 15

code_snippet: #include <vector>
#include <algorithm>
#include <map>
#include <string>
#include <queue>
#include <iostream>
using namespace std;

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

const int INF = 1 << 29;

vector<string> get_next_board(const vector<string> &board) {
    int N = board.size();
    vector<string> res(N, string(N, '.'));

    // vector<string> sample = {".....", "##.@.", "#....", "...#.", "##.##"};
    
    for(int i=0; i<N; i++) {
        for(int j=0; j<N; j++) {
            int cnt = 0;            
            for(int k=0; k<8; k++) {
                int ni = i + dx[k], nj = j + dy[k];
                if(ni < 0 or ni >= N or nj < 0 or nj >= N) continue;
                cnt += (board[ni][nj] == '#' or board[ni][nj] == '@');
            }

            /*
            if(sample == board) {
                fprintf(stderr, "i = %d, j = %d, cnt = %d\n", i, j, cnt);
            }
            */

            if(board[i][j] == '#') {
                if(cnt == 2 or cnt == 3) res[i][j] = '#';
                else res[i][j] = '.';
            }
            else if(board[i][j] == '@') {
                res[i][j] = '@';
            }
            else {
                if(cnt == 3) res[i][j] = '#';
                else res[i][j] = '.';
            }
        }
    }

    /*
    if(sample == board) {
        for(int i=0; i<N; i++) {
            cerr << "# " << res[i] << endl;
        }
        for(int i=0; i<N; i++) {
            cerr << "? " << board[i] << endl;
        }
    }
    */
    return res;
}

int bfs(const vector<string> &board, int ax, int ay) {
    map< vector<string>, int > state;
    int N = board.size();
    state[board] = 0;

    queue< tuple< vector<string>, int, int> > que;
    que.emplace(board, ax, ay);

    int res = INF;
    while(que.size()) {
        vector<string> B; int x, y;
        tie(B, x, y) = que.front(); que.pop();
        int cost = state[B];
        
        int cnt = 0;
        for(int i=0; i<N; i++) {
            for(int j=0; j<N; j++) {
                if(B[i][j] == '#') {
                    cnt = 1;
                    break;
                }
            }
        }
        if(cnt == 0) {
            res = cost;
            break;
        }
        
        for(int k=0; k<8; k++) {
            int nx = x + dx[k], ny = y + dy[k];
            if(nx < 0 or nx >= N or ny < 0 or ny >= N) continue;
            if(B[nx][ny] == '#') continue;
            swap(B[x][y], B[nx][ny]);
            vector<string> NB = get_next_board(B);
            if(!state.count(NB)) {
                state[NB] = cost + 1;
                que.emplace(NB, nx, ny);
            }
            swap(B[x][y], B[nx][ny]);
        }
    }
    return res;
}

int solve_testcase() {
    int N; cin >> N;
    if(N == 0) return 1;

    vector<string> board(N);
    int ax = -1, ay = -1;
    for(int i=0; i<N; i++) {
        cin >> board[i];
        for(int j=0; j<N; j++) {
            if(board[i][j] == '@') {
                ax = i, ay = j;
            }
        }
    }

    int ans = bfs(board, ax, ay);
    cout << (ans == INF ? -1 : ans) << endl;
    return 0;
}

int main() {
    while(!solve_testcase());
    return 0;
}
accuracy: 1
time_ms: 2880
memory_kb: 13584
final_rank: 18

code_snippet: #include <vector>
#include <algorithm>
#include <map>
#include <string>
#include <queue>
#include <iostream>
using namespace std;

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

const int INF = 1 << 29;

vector<string> get_next_board(const vector<string> &board) {
    int N = board.size();
    vector<string> res(N, string(N, '.'));

    // vector<string> sample = {".....", "##.@.", "#....", "...#.", "##.##"};
    
    for(int i=0; i<N; i++) {
        for(int j=0; j<N; j++) {
            int cnt = 0;            
            for(int k=0; k<8; k++) {
                int ni = i + dx[k], nj = j + dy[k];
                if(ni < 0 or ni >= N or nj < 0 or nj >= N) continue;
                cnt += (board[ni][nj] == '#' or board[ni][nj] == '@');
            }

            /*
            if(sample == board) {
                fprintf(stderr, "i = %d, j = %d, cnt = %d\n", i, j, cnt);
            }
            */

            if(board[i][j] == '#') {
                if(cnt == 2 or cnt == 3) res[i][j] = '#';
                else res[i][j] = '.';
            }
            else if(board[i][j] == '@') {
                res[i][j] = '@';
            }
            else {
                if(cnt == 3) res[i][j] = '#';
                else res[i][j] = '.';
            }
        }
    }

    /*
    if(sample == board) {
        for(int i=0; i<N; i++) {
            cerr << "# " << res[i] << endl;
        }
        for(int i=0; i<N; i++) {
            cerr << "? " << board[i] << endl;
        }
    }
    */
    return res;
}

int bfs(const vector<string> &board, int ax, int ay) {
    map< vector<string>, int > state;
    int N = board.size();
    state[board] = 0;

    queue< tuple< vector<string>, int, int> > que;
    que.emplace(board, ax, ay);

    int res = INF;
    while(que.size()) {
        vector<string> B; int x, y;
        tie(B, x, y) = que.front(); que.pop();
        int cost = state[B];
        
        int cnt = 0;
        for(int i=0; i<N; i++) {
            for(int j=0; j<N; j++) {
                if(B[i][j] == '#') {
                    cnt = 1;
                    break;
                }
            }
        }
        if(cnt == 0) {
            res = cost;
            break;
        }
        
        for(int k=0; k<8; k++) {
            int nx = x + dx[k], ny = y + dy[k];
            if(nx < 0 or nx >= N or ny < 0 or ny >= N) continue;
            if(B[nx][ny] == '#') continue;
            swap(B[x][y], B[nx][ny]);
            vector<string> NB = get_next_board(B);
            if(!state.count(NB)) {
                state[NB] = cost + 1;
                que.emplace(NB, nx, ny);
            }
            swap(B[x][y], B[nx][ny]);
        }
    }
    return res;
}

int solve_testcase() {
    int N; cin >> N;
    if(N == 0) return 1;

    vector<string> board(N);
    int ax = -1, ay = -1;
    for(int i=0; i<N; i++) {
        cin >> board[i];
        for(int j=0; j<N; j++) {
            if(board[i][j] == '@') {
                ax = i, ay = j;
            }
        }
    }

    int ans = bfs(board, ax, ay);
    cout << (ans == INF ? -1 : ans) << endl;
    return 0;
}

int main() {
    while(!solve_testcase());
    return 0;
}
accuracy: 1
time_ms: 2890
memory_kb: 13640
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

//INSERT ABOVE HERE

int dy[]={-1,-1,-1,0,1,1,1,0};
int dx[]={-1,0,1,1,1,0,-1,-1};
struct State{
  vector<string> st;
  State(int n):st(n){}

  int in(int y,int x) const{
    return 0<=y&&y<(int)st.size()&&0<=x&&x<(int)st[0].size();
  }

  State next() const{
    State res(*this);

    int n=st.size();
    for(int i=0;i<n;i++){
      for(int j=0;j<n;j++){
        if(st[i][j]=='@') continue;

        int cnt=0;
        for(int k=0;k<8;k++){
          int ny=i+dy[k],nx=j+dx[k];
          if(!in(ny,nx)) continue;
          if(st[ny][nx]!='.') cnt++;
        }

        res.st[i][j]='.';
        if(st[i][j]=='#'){
          if(cnt==2) res.st[i][j]='#';
          if(cnt==3) res.st[i][j]='#';
        }
        if(st[i][j]=='.'){
          if(cnt==3) res.st[i][j]='#';
        }
      }
    }
    return res;
  }

  vector<State> move() const{
    int n=st.size();
    int y=-1,x=-1;
    for(int i=0;i<n;i++)
      for(int j=0;j<n;j++)
        if(st[i][j]=='@') y=i,x=j;

    vector<State> adj;
    for(int k=0;k<8;k++){
      int ny=y+dy[k],nx=x+dx[k];
      if(!in(ny,nx)) continue;
      if(st[ny][nx]=='#') continue;
      State res(*this);
      swap(res.st[y][x],res.st[ny][nx]);
      adj.emplace_back(res.next());
    }
    return adj;
  }
};

signed main(){
  int n;
  while(cin>>n,n){
    State init(n);
    for(int i=0;i<n;i++) cin>>init.st[i];

    map<vector<string>, int> dist;
    queue<State> que;
    dist[init.st]=0;
    que.emplace(init);

    int ans=-1;
    while(!que.empty()){
      auto v=que.front();que.pop();

      int cnt=0;
      for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
          if(v.st[i][j]=='#') cnt++;
      if(cnt==0){
        ans=dist[v.st];
        break;
      }

      auto adj=v.move();
      for(auto u:adj){
        if(dist.count(u.st)) continue;
        dist[u.st]=dist[v.st]+1;
        que.emplace(u);
      }
    }
    cout<<ans<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 3330
memory_kb: 10792
final_rank: 17

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
typedef double ld;
typedef complex<ld> Point;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
const ld eps = 1e-6;
const ld pi = acos(-1.0);
typedef pair<ld, ld> LDP;
typedef pair<ll, ll> LP;

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

int n;
map<P, bool> used;
//map<P, int> memo;
char mp[5][5];

vector<P> nexc(int loc, int s) {
	//cout << loc << " " << s << endl;
	//if (s == 0)return 0;
	vector<P> ret;
	//if (used[{loc, s}])return memo[{loc, s}];
	//used[{loc, s}] = true;
	vector<vector<bool>> g(n);
	rep(i, n) {
		g[i].resize(n);
		rep(j, n) {
			int z = i * n + j;
			if (s&(1 << z))g[i][j] = true;
			else g[i][j] = false;
		}
	}
	int x = loc / n, y = loc % n;
	rep(k, 8) {
		int nx = x + dx[k], ny = y + dy[k];
		if (nx < 0 || ny < 0 || nx >= n || ny >= n)continue;
		if (g[nx][ny])continue;
		int nloc = nx * n + ny;
		int nex = 0;
		rep(i, n) {
			rep(j, n) {
				int z = i * n + j;
				if (z == nloc)continue;
				
				int cnt = 0;
				rep(l, 8) {
					int sx = i + dx[l], sy = j + dy[l];
					if (sx < 0 || sy < 0 || sx >= n || sy >= n)continue;
					if (g[sx][sy]||sx*n+sy==nloc)cnt++;
				}
				if (g[i][j]) {
					if (cnt == 3 || cnt == 2)nex += (1 << z);
				}
				else {
					if (cnt == 3)nex += (1 << z);
				}
			}
		}
		if (!used[{nloc, nex}]) {
			used[{nloc, nex}] = true;
			ret.push_back({ nloc,nex });
		}
	}
	return ret;
}

void solve(){
	used.clear(); 
	//memo.clear();
	int s = 0;
	int x = 0;
	rep(i, n) {
		rep(j, n) {
			cin >> mp[i][j];
			int z = i * n + j;
			if (mp[i][j] == '#') {
				s += (1 << z);
			}
			else if (mp[i][j] == '@') {
				x = z;
			}
		}
	}
	queue<P> q; q.push({ x,s }); used[{x, s}] = true;
	int tmp = 0;
	while (!q.empty()) {
		int len = q.size();
		rep(aa, len) {
			P p = q.front(); q.pop();
			x = p.first, s = p.second;
			if (s == 0) {
				cout << tmp << endl; return;
			}
			vector<P> c = nexc(x, s);
			rep(i, c.size())q.push(c[i]);
		}
		tmp++;
	}
	cout << -1 << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	while (cin >> n, n) {
		solve();
	}
	//stop
		return 0;
}
accuracy: 1
time_ms: 1430
memory_kb: 4292
final_rank: 13