/*
* Problem :: 1261 / 알고스팟
*
* Kind :: BFS (ReVisit)
*
* Insight
* - 거리의 정의가 실제 미로에서 이동한 거리가 아닌 벽을 부순 개수로 정의된다
* + 즉, 이동 거리의 최소가 아닌 벽을 부순 개수의 최소를 구하기 위해서는
* 이미 방문했던 칸이라도 그때 최소로 벽을 부숴서 방문했던 건지 확인해야한다
* 확인 결과, 최소가 아니라면 정보를 갱신시켜준다
*
* Point
* - Queue 가 아닌 Deque 을 사용해서,
* 벽을 부술 때는 Deque 뒤에다가 넣고, 벽을 안 부술 때는 Deque 앞에다 넣으면서,
* Deque 맨 앞부터 하나씩 꺼내서 방문하면
* 처음 (N, M) 에 방문했을 때 벽을 부순 개수가 최소가 되도록 강제할 수 있다
*/
//
// BOJ
// ver.C++
//
// Created by GGlifer
//
// Open Source
#include <iostream>
#include <deque>
using namespace std;
#define endl '\n'
// Set up : Global Variables
int M, N;
char maze[100][100];
bool isVisited[100][100];
int wallCount[100][100];
struct Point { int y, x; };
int dy[4] = {+1, 0, 0, -1};
int dx[4] = {0, +1, -1, 0};
// Set up : Functions Declaration
bool isValid(int y, int x);
int main()
{
// Set up : I/O
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Set up : Input
cin >> M >> N;
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) {
cin >> maze[i][j];
}
}
// Process
/* Queue 가 아닌 Deque 으로 이용해서 BFS */
deque<Point> deq;
/* 문제는 (1,1) 부터, 코드는 (0,0) 부터 */
deq.push_back({0, 0});
isVisited[0][0] = true;
wallCount[0][0] = 0;
while (not(deq.empty())) {
Point c = deq.front(); deq.pop_front();
int cy = c.y;
int cx = c.x;
if (cy == N-1 && cx == M-1) break;
for (int i=0; i<4; i++) {
int ny = cy + dy[i];
int nx = cx + dx[i];
/* 유효한 좌표라면 */
if (isValid(ny, nx)) {
/* 빈칸 일 때 */
if (maze[ny][nx] == '0') {
/* 방문하지 않았거나, 방문했더라도 벽을 부순 개수가 최소가 아니라면 */
if (not(isVisited[ny][nx])
|| wallCount[cy][cx] < wallCount[ny][nx])
{
/* 방문해서 정보를 갱신 */
isVisited[ny][nx] = true;
wallCount[ny][nx] = wallCount[cy][cx];
/* Deque 앞에 추가 - 벽을 부수지 않는 길부터 확인 */
deq.push_front({ny, nx});
}
}
/* 장애물이 있을 때 */
if (maze[ny][nx] == '1') {
/* 방문하지 않았거나, 방문했더라도 벽을 부순 개수가 최소가 아니라면 */
if (not(isVisited[ny][nx])
|| wallCount[cy][cx]+1 < wallCount[ny][nx])
{
/* 방문해서 정보를 갱신 */
isVisited[ny][nx] = true;
wallCount[ny][nx] = wallCount[cy][cx]+1;
/* Deque 뒤에 추가 - 벽을 부수고 간 길은 나중에 확인 */
deq.push_back({ny, nx});
}
}
}
}
}
// Control : Output
cout << wallCount[N-1][M-1] << endl;
}
// Helper Functions
bool isValid(int y, int x)
/* 주어진 좌표가 유효하다면 ture 를 반환, 그 외 false 를 반환 */
{
return y >= 0 && y < N && x >= 0 && x < M;
}