#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <map>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

static const int MASK = 15;
inline int Get(ll state, int index) {
  int ret = (state >> (index * 4)) & MASK;
  return ((ret << 28) >> 28); // 15 to -1
}
inline void Set(ll &state, int v, int index) {
  state &= ~((ll)MASK << (index * 4));
  state |= (ll)(MASK & v) << (index * 4);
}

//===========================

int h, w;
char field[20][20];
map<ll, int> memo[20][20];

char mapto[10];
int calc(ll connect, int x, int y);

int NextState(ll connect, int x, int y, char c) {
  int ret = 0;
  int pc = Get(connect, x);
  int lc = -1;
  if (x != 0) { lc = Get(connect, x - 1); }
  if (c == '#') {
    ret++;
    if (lc >= 0 && lc == pc) { return -1; }
    if (lc >= 0) {
      Set(connect, lc, x);
      if (pc >= 0) {
        REP(i, w) {
          if (Get(connect, i) == pc) { Set(connect, lc, i); }
        }
      }
    } else if (pc == -1) {
      //cout << "test " << x << " " << y << endl;
      //REP(i, w) { assert(connect[i] != 7); }
      Set(connect, 7, x);
    } else {
      // do nothing
    }
  } else {
    if ((y != 0 && pc == -1) ||
        (x != 0 && lc == -1)) { return -1; }
    Set(connect, -1, x);
    if (pc != -1) {
      REP(i, w) {
        if (Get(connect, i) == pc) { goto ok; }
      }
      return -1;
ok:;
    }
  }

  {
    // Normalize
    MEMSET(mapto, -1);
    int m = 0;
    REP(i, w) {
      int v = Get(connect, i);
      if (v != -1) {
        if (mapto[v] == -1) {
          mapto[v] = m++;
        }
        Set(connect, mapto[v], i);
      }
    }
    //assert(m <= 8);
  }
  int nret = calc(connect, x + 1, y);
  if (nret == -1) { ret = -1; }
  else { ret += nret; }
  return ret;
}

int calc(ll connect, int x, int y) {
  if (memo[y][x].count(connect)) { return memo[y][x][connect]; }
  if (y == h) {
    REP(x, w) {
      if (Get(connect, x) > 0) { return -1; }
    }
    return 0;
  }
  if (x == w) { return calc(connect, 0, y + 1); }
  int ret = -1;
  if (field[y][x] == '?') {
    ret = max(ret, NextState(connect, x, y, '#'));
    ret = max(ret, NextState(connect, x, y, '.'));
  } else {
    ret = max(ret, NextState(connect, x, y, field[y][x]));
  }
  return memo[y][x][connect] = ret;
}

int main() {
  while (scanf("%d %d", &h, &w) > 0) {
    REP(y, 20) REP(x, 20) { memo[y][x].clear(); }
    REP(y, h) {
      int v = scanf("%s", field[y]);
      assert(v == 1);
    }
    int ans = -1;
    if (w == 1) {
      int cnt = 0;
      REP(y, h) { if (field[y][0] != '.') { cnt++; } }
      if (h == 2) { if (cnt != 0) { ans = cnt; } }
      else {
        ans = cnt;
        FOR(y, 1, h - 1) {
          if (field[y][0] == '.') { ans = -1; }
        }
      }
    } else {
      ans = calc(-1, 0, 0);
    }
    printf("%d\n", ans);
  }
}

Measured memory_bytes: 9912