#include<cstdio>
#include<queue>
using namespace std;
const int m = 55;
const int dr[] = { 1,0,-1,0 };
const int dc[] = { 0,1,0,-1 }; // down right up left
const int INF = 1 << 22;
char im[m][m];
int vis[4][m][m];
struct pos {
int r, c;
int current_dir;
pos() {}
pos(int ir, int ic, int icd) : r(ir), c(ic), current_dir(icd) {}
void set_pos(int ir, int ic) {
r = ir;
c = ic;
}
};
int main() {
int n;
scanf("%d", &n);
pos start, end;
bool is_start = false;
for (int r = 0; r < n; r++) {
scanf("%s", im[r]);
for (int c = 0; c < n; c++) {
if (im[r][c] == '#') {
if(!is_start) is_start = true, start.set_pos(r, c);
else if (is_start) end.set_pos(r, c);
}
}
}
queue<pos> Q;
for (int i = 0; i < 4; i++) {
Q.push(pos(start.r, start.c, i));
for (int r = 0; r < n; r++) {
for (int c = 0; c < n; c++) {
vis[i][r][c] = INF;
}
}
vis[i][start.r][start.c] = 0;
} // INF;
while (!Q.empty()) {
pos here = Q.front();
Q.pop();
int hr = here.r;
int hc = here.c;
int hd = here.current_dir;
int tr = here.r + dr[hd];
int tc = here.c + dc[hd];
if (tr < 0 || n <= tr || tc < 0 || n <= tc) continue;
if (im[tr][tc] == '*')continue;
if (im[tr][tc] == '!') {
if (vis[hd][tr][tc] > vis[hd][hr][hc]) {
vis[hd][tr][tc] = vis[hd][hr][hc]; // 설치 X
Q.push(pos(tr, tc, hd)); // 그방향 그대로 간다.
}
if (vis[(hd + 1) % 4][tr][tc] > vis[hd][hr][hc] + 1) {
vis[(hd + 1) % 4][tr][tc] = vis[hd][hr][hc] + 1;
Q.push(pos(tr, tc, (hd + 1) % 4)); // 45도 +1
}
if (vis[(hd + 3) % 4][tr][tc] > vis[hd][hr][hc] + 1) {
vis[(hd + 3) % 4][tr][tc] = vis[hd][hr][hc] + 1;
Q.push(pos(tr, tc, (hd + 3) % 4)); // 45도 +1
}
}
else if (im[tr][tc] == '.') {
if (vis[hd][tr][tc] > vis[hd][hr][hc]) {
vis[hd][tr][tc] = vis[hd][hr][hc];
Q.push(pos(tr, tc, hd)); // 그방향 그대로 간다.
}
}
else if (im[tr][tc] == '#') {
if (vis[hd][tr][tc] > vis[hd][hr][hc]) {
vis[hd][tr][tc] = vis[hd][hr][hc];
}
}
}
int ans = INF;
for (int i = 0; i < 4; i++) {
if (ans > vis[i][end.r][end.c]) {
ans = vis[i][end.r][end.c];
}
}
printf("%d\n", ans);
return 0;
}
// 7% WA
// 15% WA?
// 23% WA