//注:该代码,N和M与题目中的顺序相反
#include<iostream>
#include<vector>
using namespace std;
typedef struct//节点
{
    int x;
    int y;
}node;

int dx[4] = { 1,-1,0,0 };//用于判断上下左右时使用
int dy[4] = { 0,0,1,-1 };//同上
int main()
{
    int M, N;
    cin >> M >> N;
    vector<vector<char>> m(M);//用于储存矩阵
    vector<vector<int>> num(M);//用于储存走到矩阵各点的距离
    for (int x = 0; x < M; x++)//扩容
    {
        m[x].resize(N);
        num[x].resize(N);
    }
    for (int x = 0; x < M; x++)//输入矩阵元素
    {
        getchar();
        for (int y = 0; y < N; y++)
        {
            scanf("%c", &m[x][y]);
        }
    }
    num[0][0] = 1;//走到0,0坐标默认为1
    m[0][0] = '0';//将0,0坐标的元素变'0',以免再次被查找
    int flag = 1;//用于判断是否走到了右下角的点
    node t = { 0,0 };
    vector<node>q;//用于保存路上走到的点的坐标
    q.push_back(t);//将0,0点存到路径动态数组
    while (q.size())//当数组中没有元素时代表没路可走,即停止
    {
        t = q[0];//保存第一个点,以此点开始查找周围
        q.erase(q.begin());//将第一个点从数组中去除,以免下次被调用
        if (t.x == M - 1 && t.y == N - 1)//如果当前的点是右下角的点,就直接输出当前num矩阵中该点的数即可,第一次走到定为最小
        {
            flag = 0;//将flag变0,代表已走到
            cout << num[M - 1][N - 1];
            break;
        }
        for (int i = 0; i < 4; i++)//上下左右查找为'1'的点
        {
            int _x = t.x + dx[i];
            int _y = t.y + dy[i];
            if (_x < 0 || _x >= M || _y < 0 || _y >= N)//坐标越界跳过,执行下一次循环
            {
                continue;
            }
            if (m[_x][_y] == '1')//找到为'1'的点
            {
                m[_x][_y] = '0';//将该点变为'0'防止下次被查找
                num[_x][_y] = num[t.x][t.y] + 1;//令该点对应的num的数变为前一个点的+1
                node new_t = { _x,_y };
                q.push_back(new_t);//因为该坐标可走,所以将新的坐标保存到数组中,做下次查找
            }
        }
    }
    if (flag)//如果找到右下角得点,不能输出,反之输出-1
    {
        cout << -1;
    }
    return 0;
}