//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using db = double;
using ld = long double;
template<typename T> using V = vector<T>;
template<typename T> using VV = vector<vector<T>>;
#define fs first
#define sc second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(),(v).end()
#define siz(v) (ll)(v).size()
#define rep(i,a,n) for(ll i=a;i<(ll)(n);++i)
#define repr(i,a,n) for(ll i=n-1;(ll)a<=i;--i)
#define ENDL '\n'
typedef pair<int,int> Pi;
typedef pair<ll,ll> PL;
constexpr ll mod = 1000000007;
constexpr ll INF = 1000000099;
constexpr ll LINF = (ll)(1e18 +99);
const vector<ll> dx={-1,1,0,0},dy={0,0,-1,1};
template<typename T,typename U> inline bool chmin(T& t, const U& u){if(t>u){t=u;return 1;}return 0;}
template<typename T,typename U> inline bool chmax(T& t, const U& u){if(t<u){t=u;return 1;}return 0;}
template<typename T> inline T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<typename T,typename Y> inline T mpow(T a, Y n) {
  T res = 1;
  for(;n;n>>=1) {
    if (n & 1) res = res * a;
    a = a * a;
  }
  return res;
}

template<typename T>
class UnionFind {
public:

	vector<T> Parent;
 
	UnionFind(T N) {
		Parent = vector<T>(N, -1);
	}
 
	T root(T A) {
		if (Parent[A] < 0) return A;
		return Parent[A] = root(Parent[A]);
	}
 
	T size(T A) {
		return -Parent[root(A)];
	}
 
	bool connect(T A, T B) {
		A = root(A);
		B = root(B);
		if (A == B) {
			return false;
		}
		if (size(A) < size(B)) swap(A, B);
		Parent[A] += Parent[B];
		Parent[B] = A;
 
		return true;
	}

    bool same(T A,T B){
        return root(A)==root(B);
    }
};

signed main(){
  cin.tie(0);ios::sync_with_stdio(false);
  cout<<fixed<<setprecision(20);
  int h,w;cin>>h>>w;
  VV<char> v(h,V<char>(w));
  VV<int> ans(h,V<int>(w,INF));
  VV<bool> used(h,V<bool>(w,false));

  rep(i,0,h)rep(j,0,w)cin>>v[i][j];
  
  deque<int> q;
  q.push_back(0);
  q.push_back(0);
  if(v[0][0]=='#')q.push_back(1);
  else q.push_back(0);
  used[0][0]=true;

  while(q.size()){
    int g=q.front();
    q.pop_front();
    int r=q.front();
    q.pop_front();
    int cost=q.front();
    q.pop_front();
    chmin(ans[g][r],cost);

    if(g<h-1){
      if(v[g][r]=='.' && v[g+1][r]=='#'){
        if(cost+1<ans[g+1][r]){
          ans[g+1][r]=cost+1;
          q.push_back(g+1);
          q.push_back(r);
          q.push_back(cost+1);
        }
      }else{
        if(cost<ans[g+1][r]){
          q.push_front(cost);
          q.push_front(r);
          q.push_front(g+1);
        }
      }
      used[g+1][r]=true;
    }

    if(r<w-1){
      if(v[g][r]=='.' && v[g][r+1]=='#'){
        if(cost+1<ans[g][r+1]){
          ans[g][r+1]=cost+1;
          q.push_back(g);
          q.push_back(r+1);
          q.push_back(cost+1);
        }
      }else{
        if(cost<ans[g][r+1]){
          q.push_front(cost);
          q.push_front(r+1);
          q.push_front(g);
        }
      }
      used[g][r+1]=true;
    }
  }

  /*UnionFind<int> u(h*w);
  rep(i,0,h)rep(j,0,w){
    if(i<h-1 && v[i][j]=='#' && v[i+1][j]=='#')u.connect(w*i+j,w*(i+1)+j);
    if(j<w-1 && v[i][j]=='#' && v[i][j+1]=='#')u.connect(w*i+j,w*i+j+1);
  }

  if(u.same(0,h*w-1))cout<<0<<ENDL;
  else */cout<<ans[h-1][w-1]<<ENDL;
}
//! ( . _ . ) ! 
//CHECK overflow,vector_size,what to output?

Measured memory_bytes: 384