#include <bits/stdc++.h>
#pragma gcc optimize("ofast")
using namespace std;
stack<pair<int, int> > path;
vector<string> v;
bool pos(int n, int m) {
  queue<pair<int, int> > q;
  bool vis[n][m];
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) vis[i][j] = false;
  }
  q.push({0, 0});
  vis[0][0] = true;
  while (!q.empty()) {
    pair<int, int> p = q.front();
    q.pop();
    if (p.first + 1 < n && !vis[p.first + 1][p.second] &&
        v[p.first + 1][p.second] != '#') {
      vis[p.first + 1][p.second] = true;
      q.push({p.first + 1, p.second});
    }
    if (p.second + 1 < m && !vis[p.first][p.second + 1] &&
        v[p.first][p.second + 1] != '#') {
      vis[p.first][p.second + 1] = true;
      q.push({p.first, p.second + 1});
    }
  }
  if (vis[n - 1][m - 1]) return true;
  return false;
}
bool vis2[1000005];
void dfs(int n, int m, int i, int j) {
  if (i == n - 1 && j == m - 1) {
    while (!path.empty()) {
      auto uj = path.top();
      path.pop();
      v[uj.first][uj.second] = '#';
    }
    v[0][0] = '.';
    v[n - 1][m - 1] = '.';
    if (pos(n, m)) {
      cout << "2\n";
    } else {
      cout << "1\n";
    }
    exit(0);
  }
  if (i + 1 < n && v[i + 1][j] != '#' && !(vis2[(i + 1) * m + j])) {
    path.push({i + 1, j});
    vis2[(i + 1) * m + j] = true;
    dfs(n, m, i + 1, j);
    path.pop();
  }
  if (j + 1 < m && v[i][j + 1] != '#' && !(vis2[(i)*m + (j + 1)])) {
    path.push({i, j + 1});
    vis2[(i * m) + (j + 1)] = true;
    dfs(n, m, i, j + 1);
    path.pop();
  }
  return;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  string in;
  for (int i = 0; i < n; i++) {
    cin >> in;
    v.push_back(in);
  }
  int minn = min(n, m);
  if (minn == 1) {
    if (pos(n, m)) {
      cout << "1"
           << "\n";
    } else {
      cout << "0"
           << "\n";
    }
  } else {
    if (pos(n, m)) {
      path.push({0, 0});
      vis2[0] = true;
      dfs(n, m, 0, 0);
    } else {
      cout << "0"
           << "\n";
    }
  }
}
