import std.algorithm, std.array, std.container, std.range, std.bitmanip; import std.numeric, std.math, std.bigint, std.random, core.bitop; import std.string, std.regex, std.conv, std.stdio, std.typecons; class UnionFind { size_t[] par; this(size_t n) { par = new size_t[](n); par[] = size_t.max; } size_t find(size_t i) { if (par[i] == size_t.max) { return i; } else { par[i] = find(par[i]); return par[i]; } } void unite(size_t i, size_t j) { auto pi = find(i), pj = find(j); if (pi != pj) par[pj] = pi; } } void main() { auto rd = readln.split.map!(to!size_t); auto n = rd[0], m = rd[1]; auto sij = iota(n).map!(_ => readln.chomp.map!(c => c != '.').array).array; auto uf = new UnionFind(n * m); foreach (i; 0..n) foreach (j; 0..m) { if (sij[i][j]) { if (i > 0 && sij[i - 1][j]) uf.unite(i * m + j, (i - 1) * m + j); if (i < n - 1 && sij[i + 1][j]) uf.unite(i * m + j, (i + 1) * m + j); if (j > 0 && sij[i][j - 1]) uf.unite(i * m + j, i * m + (j - 1)); if (j < m - 1 && sij[i][j + 1]) uf.unite(i * m + j, i * m + (j + 1)); } } auto s = new int[][](n * m, 2); foreach (i; 0..n) foreach (j; 0..m) if (sij[i][j]) s[uf.find(i * m + j)][(i + j) % 2] += 1; auto r = 0; foreach (i; 0..n * m) { auto a = min(s[i][0], s[i][1]); r += a * 100; s[i][0] -= a; s[i][1] -= a; } auto l1 = 0, l2 = 0; foreach (i; 0..n * m) { l1 += s[i][0]; l2 += s[i][1]; } auto b = min(l1, l2); r += 10 * b; l1 -= b; l2 -= b; r += l1 + l2; writeln(r); }