staticinlineboollabel_present(uint32_t front, int lab) { for (int i = 0; i < W; i++) if (get_lab(front, i) == lab) returntrue; returnfalse; }
staticinlineintmax_label(uint32_t front) { int k = 0; for (int i = 0; i < W; i++) k = max(k, get_lab(front, i)); return k; }
staticinline Profile canonical(uint32_t front, uint64_t sizes) { int mp[8]; int ns[8]; memset(mp, 0, sizeof(mp)); memset(ns, 0, sizeof(ns)); int k = 0; int lab[W]; for (int i = 0; i < W; i++) { int x = get_lab(front, i); if (x == 0) { lab[i] = 0; continue; } if (mp[x] == 0) { mp[x] = ++k; ns[k] = get_size(sizes, x); } lab[i] = mp[x]; } uint32_t nfront = 0; for (int i = 0; i < W; i++) nfront |= (uint32_t)lab[i] << (3 * i); uint64_t nsizes = 0; for (int i = 1; i <= k; i++) nsizes |= (uint64_t)ns[i] << (6 * (i - 1)); return Profile{nfront, nsizes}; }
staticinline Profile trans_white(Profile p, int c) { uint32_t front = p.front; uint64_t sizes = p.sizes; int U = get_lab(front, c); front = set_lab(front, c, 0); if (U != 0 && !label_present(front, U)) sizes = set_size(sizes, U, 0); returncanonical(front, sizes); }
staticinline pair<Profile, int> trans_black(Profile p, int c) { uint32_t front = p.front; uint64_t sizes = p.sizes; int L = (c > 0) ? get_lab(front, c - 1) : 0; int U = get_lab(front, c); int k = max_label(front); int new_sz = 0;
if (L == 0 && U == 0) { int nid = k + 1; sizes = set_size(sizes, nid, 1); front = set_lab(front, c, nid); new_sz = 1; } elseif (L != 0 && U == 0) { int s = get_size(sizes, L) + 1; sizes = set_size(sizes, L, s); front = set_lab(front, c, L); new_sz = s; } elseif (L == 0 && U != 0) { int s = get_size(sizes, U) + 1; sizes = set_size(sizes, U, s); front = set_lab(front, c, U); new_sz = s; } else { if (L == U) { int s = get_size(sizes, L) + 1; sizes = set_size(sizes, L, s); front = set_lab(front, c, L); new_sz = s; } else { int root = min(L, U); int other = max(L, U); int s = get_size(sizes, root) + get_size(sizes, other) + 1; sizes = set_size(sizes, root, s); sizes = set_size(sizes, other, 0); for (int i = 0; i < W; i++) if (get_lab(front, i) == other) front = set_lab(front, i, root); front = set_lab(front, c, root); new_sz = s; } }
staticinlinevoidadd_dist(array<ll, BMAX + 1> &dst, array<ll, BMAX + 1> const &src, int m) { if (m <= 0) { for (int b = 0; b <= BMAX; b++) dst[b] += src[b]; return; } ll pref = 0; for (int b = 0; b < m; b++) pref += src[b]; dst[m] += pref; for (int b = m; b <= BMAX; b++) dst[b] += src[b]; }
for (int r = 0; r < H; r++) { for (int c = 0; c < W; c++) { ndp.clear(); ndp.reserve(dp.size() * 2 + 16); for (autoconst &it : dp) { Profile st = it.first; autoconst &dist = it.second;
auto t1 = trans_black(st, c); Profile s1 = t1.first; int m = t1.second; auto &d1 = ndp[s1]; add_dist(d1, dist, m); } dp.swap(ndp); } }
ll num = 0; for (autoconst &it : dp) { autoconst &dist = it.second; for (int b = 0; b <= BMAX; b++) num += (ll)dist[b] * (ll)b; } double ans = (double)num; for (int i = 0; i < W * H; i++) ans /= 2.0L; cout.setf(std::ios::fixed); cout << setprecision(8) << ans << "\n"; return0; }