/*
* Problem :: 2665 / 미로만들기
*
* Kind :: BFS
*
* Insight
* - dp[i][j] = (1,1) 에서 (i,j) 로 갈 때
* 검은 방을 흰 방으로 바꾸어야 할 최소의 수
* + (1,1) 에서 BFS 돌면서
* dp[i][j] 를 갱신시켜주면 되겠다
* # dp[i][j] = 2 였다가 BFS 도중에 1 로 바뀔 수 있다!
* (i,j) 로 가는 앞선 방법보다 현재 방법이
* 검은 방을 흰 방으로 바꾸어야 할 최소의 수가 더 적을 수 있다
* -> BFS 에서 Queue 를 통해 순회할 때
* front 의 (i,j) 를 다루어줄 때 dp[i][j] 가 최소임을 보장할 수 없을까?
* => Deque 을 사용해서
* 흰방에서 흰방으로 갈 때는 dp[i][j] 가 그대로이므로 Deque 의 앞에 넣어주고
* 흰방에서 검은방으로 갈 때는 dp[i][j] 가 증가하므로 Deque 의 뒤에 넣어주자
* 이러면, 항상 Deque 에서 front 의 (i,j) 를 다루어줄 때
* dp[i][j] 가 항상 최소임을 보장할 수 있다!
* (어찌보면 front 의 (i,j) 방문시 (1,1) 에서 (i,j) 까지의 최단거리인
* dp[i][j] 를 보장하므로 Dijkstra 랑 비슷한듯?)
*/
//
// BOJ
// ver.C++
//
// Created by GGlifer
//
// Open Source
#include <iostream>
#include <deque>
#include <cstring>
#include <functional>
using namespace std;
#define endl '\n'
// Set up : Global Variables
struct Point { int y, x; };
int dy[4] = {+1, 0, 0, -1};
int dx[4] = {0, +1, -1, 0};
// Set up : Functions Declaration
/* None */
int main()
{
// Set up : I/O
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Set up : Input
int N; cin >> N;
char A[N][N];
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
cin >> A[i][j];
// Process
/* 주어진 좌표 (y,x) 가 유효하면 true 를 반환, 그 외 false 를 반환 */
function<bool(int,int)> isValid = [N](int y, int x){
return y >= 0 && y < N && x >= 0 && x < N;
};
int dp[N][N]; /* dp[i][j] = (1,1) 에서 (i,j) 로 갈 때
* 검은 방을 흰 방으로 바꾸어야 할 최소의 수 */
memset(dp, -1, sizeof(dp)); /* dp 초기화 */
deque<Point> deq;
dp[0][0] = 0;
deq.push_back({0, 0});
int ans = -1;
while (not(deq.empty())) {
auto [cy, cx] = deq.front();
deq.pop_front();
/* 끝방에 도착했다면 */
if (cy == N-1 && cx == N-1) {
ans = dp[cy][cx];
break;
}
for (int i=0; i<4; i++) {
int ny = cy + dy[i];
int nx = cx + dx[i];
if (isValid(ny, nx)) { /* 좌표가 유효하고 */
/* 흰방 -> 흰방 */
if (A[ny][nx] == '1') {
if (dp[ny][nx] == -1 || dp[ny][nx] > dp[cy][cx]) {
dp[ny][nx] = dp[cy][cx];
deq.push_front({ny, nx}); /* 덱의 앞에 추가 */
}
}
/* 흰방 -> 검은방 */
if (A[ny][nx] == '0') {
if (dp[ny][nx] == -1 || dp[ny][nx] > dp[cy][cx] + 1) {
dp[ny][nx] = dp[cy][cx] + 1;
deq.push_back({ ny, nx }); /* 덱의 뒤에 추가 */
}
}
}
}
}
// Control : Output
cout << ans << endl;
}
// Helper Functions
/* None */