#include <bits/stdc++.h>

using namespace std;

#define int long long

typedef long long ll;
typedef pair<int, int> P;

struct PQ {
	int den, num;
	PQ(int den, int num) : den(den), num(num) {}
};
bool operator>(const PQ& pq1, const PQ& pq2) {
	return pq1.num * pq2.den > pq1.den * pq2.num;
}
bool operator<(const PQ& pq1, const PQ& pq2) {
	return pq2 > pq1;
}
bool operator==(const PQ& pq1, const PQ& pq2) {
	return !(pq1 > pq2) && !(pq1 < pq2);
}
bool operator>=(const PQ& pq1, const PQ& pq2) {
	return pq1 == pq2 || pq1 > pq2;
}
bool operator<=(const PQ& pq1, const PQ& pq2) {
	return pq2 >= pq1;
}

typedef pair<PQ, PQ> PQP;

int H, W;
vector<string> M;
bool dot[601][601] = {0};
bool inRange(int x, int y) {
	return 0 <= x && x < W && 0 <= y && y < H;
}
bool inRange2(int x, int y) {
	return 0 <= x && x <= W && 0 <= y && y <= H;
}
bool isWall(int x, int y) {
	if ( !inRange(x, y) ) return false;
	return M[y][x] == '#';
}
bool getDot(int x, int y) {
	if ( !inRange2(x, y) ) return false;
	return dot[y][x];
}
bool moveCheck(int x1, int y1, int x2, int y2) {
	if ( !getDot(x2, y2) ) return false;
	map<P, int> cnt;
	for (int dy = -1; dy <= 0; ++dy) {
		for (int dx = -1; dx <= 0; ++dx) {
			cnt[P(x1+dx, y1+dy)]++;
			cnt[P(x2+dx, y2+dy)]++;
		}
	}
	set<bool> s;
	for ( pair<const P, int>& p : cnt ) {
		if (p.second == 2 ) {
			s.insert(isWall(p.first.first, p.first.second));
		}
	}
	return s.size() == 2;
}
int moveX(int x0, int y0) {
	bool bfl = true, bfr = true;
	bool fl = true, fr = true;
	for (int dx = 1; dx <= W+3; ++dx) {
		fr = fr && moveCheck(x0+dx-1, y0, x0+dx, y0);
		fl = fl && moveCheck(x0-(dx-1), y0, x0-dx, y0);
		if ( !fr && !fl ) {
			if (bfl) return x0-(dx-1);
			return x0+dx-1;
		}
		bfl = fl, bfr = fr;
	}
}
int moveY(int x0, int y0) {
	bool bfl = true, bfr = true;
	bool fl = true, fr = true;
	for (int dy = 1; dy <= H+3; ++dy) {
		fr = fr && moveCheck(x0, y0+(dy-1), x0, y0+dy);
		fl = fl && moveCheck(x0, y0-(dy-1), x0, y0-dy);
		if ( !fr && !fl ) {
			if (bfl) return y0-(dy-1);
			return y0+dy-1;
		}
		bfl = fl, bfr = fr;
	}
}

PQ f(int x, int y) {
	return PQ(x, y);
}

int da = 0;
vector<PQP> r;
void addLine(int x1, int y1, int x2, int y2) {
	y1 = H-y1, y2 = H-y2;
	if ((x1 == 0 && y1 == 0) || (x2 == 0 && y2 == 0)) {
		da = 1;
		return;
	}
//	cout << x1 << " " << y1 << " " << x2 << " " << y2 << " " << (double)y1/x1 << " " << (double)y2/x2 << endl;
	PQ pq1 = f(x1, y1);
	PQ pq2 = f(x2, y2);
	if (pq2 < pq1) swap(pq1, pq2);
	r.push_back( PQP(pq1, pq2) );
}
signed main() {
	cin >> H >> W;
	M.resize(H);
	for (int i = 0; i < H; ++i) cin >> M[i];
	for (int y = 0; y <= H; ++y) {
		for (int x = 0; x <= W; ++x) {
			set<bool> s;
			for (int dx = -1; dx <= 0; ++dx) {
				for (int dy = -1; dy <= 0; ++dy) {
					s.insert( isWall(x+dx, y+dy) );
				}
			}
			dot[y][x] = s.size() == 2;
		}
	}
	int sx = -1, sy = -1;
	for (int y = 0; y < H; ++y) {
		for (int x = 0; x < W; ++x) {
			if ( isWall(x, y) ) {
				sx = x, sy = y;
				break;
			}
		}
		if (sx >= 0) break;
	}
	{
		int x = sx, y = sy;
		while (1) {
			int nx = moveX(x, y);
			int ny = moveY(nx, y);
//			assert(nx != x);
//			assert(ny != y);
			addLine(x, y, nx, y);
			addLine(nx, y, nx, ny);
			if (nx == sx && ny == sy) break;
			x = nx, y = ny;
		}
		sort(r.begin(), r.end());
		int mx = 0;
		map<PQ, int> m;
		{
			vector<PQ> v;
			for (int i = 0; i < r.size(); ++i) {
				v.push_back(r[i].first);
				v.push_back(r[i].second);
			}
			sort(v.begin(), v.end());
			v.erase(unique(v.begin(), v.end()), v.end());
			for (int i = 0; i < v.size(); ++i) {
	//			cout << v[i].first.num << " " << v[i].
				m[v[i]] = i+1;
			}
			mx = v.size();
		}
		vector<P> v;
		for (int i = 0; i < r.size(); ++i) {
//			cout << r[i].first.den << " " << r[i].first.num << " " << r[i].second.den << " " << r[i].second.num << endl;
		}
		for (int i = 0; i < r.size(); ++i) {
			v.push_back( P(m[r[i].first]-1, m[r[i].second]-1) );
		}
		for (int i = 0; i < r.size(); ++i) {
			v[i] = P(v[i].first*2, v[i].second*2);
		}
		for (int i = 0; i < v.size(); ++i) {
//			cout << v[i].first << " " << v[i].second << endl;
		}
		vector<int> cnt(mx*3, 0);
		for (int i = 0; i < v.size(); ++i) {
			if (v[i].first < v[i].second) {
				++cnt[v[i].first+1];
				--cnt[v[i].second];
			}
		}
		for (int i = 1; i < cnt.size(); ++i) {
			cnt[i] += cnt[i-1];
		}
/*
		{
			set<P> s;
			for (int i = 0; i < r.size(); ++i) {
				s.insert( P(r[i].first.den, r[i].first.num) );
				s.insert( P(r[i].second.den, r[i].second.num) );
			}
			for ( const P& p : s ) {
				int x = p.first, y = H-p.second;
				int d = 0;
				d += isWall(x-1, y);
				d += isWall(x, y-1);
				cnt[(m[PQ(p.first, p.second)]-1)*2] += d;
				cout << x << " " << y << " " << d << " " << m[PQ(p.first, p.second)]-1 << endl;
			}
		}
//		cout << cnt[4] << endl;
//		cout << m[PQ(1, 1)] << endl;
*/
		int ans = 0;
		for (int i = 0; i < cnt.size(); ++i) {
//			if (cnt[i] > ans) cout << i << endl;
			ans = max(ans, cnt[i]);
		}
		ans += da;
//		cout << ans << endl;
		assert(ans%2 == 0);
		cout << ans/2+1 << endl;
	}
}

Measured memory_bytes: 21364