Problem:
問題文

落書きの魔女 ALBERTINE は W 列 H 行の正方形のセルからなる長方形の結界の入り口に落書きをしている．この世界では落書きは必ずセルを白色か黒色で塗ることによって成り立つ．

すでに使い魔 ANJA の手によって落書きの一部が描かれているのだが，落書きの魔女は残りすべてのセルを塗り落書きを完成させたい．落書きの魔女にはあるこだわりがある．そのこだわりとは次のようなものである．

2 つの異なるセルが辺を共有するとき，2 つのセルは隣接していると呼ぶことにする．完成された落書きにおいては，任意の 2 つの黒いセルについて，片方からもう片方への隣接した黒いセルをたどるパスがちょうど 1 つだけ存在していなければならない．

どの 2 つの白色のセルも隣接してはならない．

また，落書きの魔女は黒色が好きなので，こだわりを満たした状態でなおかつ最も黒色のセルが多い落書きを完成させたい．果たして落書きの魔女は最大で何個のセルが黒色に塗られたこだわりの落書きを描くことができるだろうか．

入力形式

入力は以下の形式で与えられる．

H\ W\\
c_{11} c_{12} ... c_{1W}\\
c_{21} c_{22} ... c_{2W}\\
...\\
c_{H1} c_{H2} ... c_{HW}\\

H は結界の入り口の縦幅，W は結界の入り口の横幅を表す．

c_{ij} は各セルの状態を表す文字であり，上から i 行目，左から j 列目のセルの状態を表す．セルに黒色が塗られている場合は c_{ij} は '#' となり，白色が塗られている場合は '.'，まだ色が塗られていない場合はそうでない場合は '?' となる．

出力形式

魔女のこだわりを満たした状態でとりうる黒色のセルの個数の最大値を 1 行で出力せよ．

もしどのように塗っても魔女のこだわりを満たすように出来ない場合，-1 と出力せよ．

制約

1 ≤ H ≤ 11

1 ≤ W ≤ 11

c_{ij} は '#', '.', '?' のいずれかである．

入出力例

入力例 1

3 4
.##.
#??#
.#?#

出力例1

8

入力例 2

5 5
##?##
#???#
?????
#???#
##?##

出力例 2

19

入力例 3

9 2
##
..
??
??
??
??
??
??
??

出力例 3

-1

入力例 4

7 9
??#####??
?#?????#?
?#?????#?
?#??#??#?
?#???#?#?
??#####??
???????#?

出力例 4

44

入力例 5

11 11
???????????
???####????
???#???#???
???#???#???
???#???#???
???####????
???#???#???
???#???#???
???#???#???
???####????
???????????

出力例 5

86

Problem Setter: Flat35

Solution in C++11 (judge verdict: Accepted)

#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;

//// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt"


struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool findSet(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};


int main() {
	int H, W; cin >> H >> W;
	vector<vector<int>>field(H, vector<int>(W));
	for (int i = 0; i < H; ++i) {
		string st; cin >> st;
		for (int j = 0; j < W; ++j) {
			if (st[j] == '.') {
				field[i][j] = 0;
			}
			else if (st[j] == '#') {
				field[i][j] = 1;
			}
			else {
				field[i][j] = -1;
			}
		}
	}
	if (W == 1) {
		swap(H, W);
		vector<vector<int>>newfield(H, vector<int>(W));
		for (int i = 0; i < H; ++i) {
			for (int j = 0; j < W; ++j) {
				newfield[i][j] = field[j][i];
			}
		}
		field = newfield;
	}
	if (H == 1 && W == 1) {
		if (field[0][0] == 0) {
			cout << 0 << endl;
		}
		else {
			cout << 1 << endl;
		}
		return 0;
	}
	map<vector<int>,  int>mp;
	vector<int>start(W);
	iota(start.begin(), start.end(), 1);
	mp[start] = 0;
	int finans = -1;
	for (int y = 0; y < H; ++y) {
		map<vector<int>,int>newmp;
		for (int b = 0; b < (1 << W); ++b) {
			const bitset<11>bs(b);
			bool aaok = true;
			for (int x = 0; x < W - 1; ++x) {
				if (!bs[x] && !bs[x + 1])aaok = false;
			}
			for (int x = 0; x < W; ++x) {
				if (field[y][x] != -1) {
					if (field[y][x] != bs[x])aaok = false;
				}
			}
			if (!aaok)continue;
			for (const auto m : mp) {
				const vector<int>upbelongs(m.first);
				const int ans = m.second;
				bool ok = true;
				
				UnionFind uf(W);
				for (int l = 0; l < W; ++l) {
					for (int r = l + 1; r < W; ++r) {
						if (bs[l] && bs[r]) {
							if (upbelongs[l] && upbelongs[r]) {
								if (upbelongs[l] == upbelongs[r]) {
									uf.unionSet(l, r);
								}
							}
						}
					}
				}
				if (y) {
					for (int aa = 1; aa < 11; ++aa) {
						if (find(upbelongs.begin(), upbelongs.end(), aa) != upbelongs.end()) {
							bool aok = false;
							for (int x = 0; x < W; ++x) {
								if (upbelongs[x] == aa) {
									if (bs[x])aok = true;
								}
							}
							if (!aok)ok = false;
						}
					}
				}
					
				for (int x = 0; x < W-1; ++x) {
					if (bs[x]&&bs[x+1]) {
						if (uf.root(x) == uf.root(x + 1))ok = false;
						uf.unionSet(x, x + 1);
					}
				}
				for (int x = 0; x < W; ++x) {
					if (!bs[x] && !upbelongs[x])ok = false;
				}
				if (!ok)continue;
				else {
					map<int, int>amp;
					int anum = 1;
					vector<int>fins(W);
					for (int x = 0; x < W; ++x) {
						if (bs[x]) {
							if (amp.find(uf.root(x)) == amp.end()) {
								amp[uf.root(x)] = anum;
								anum++;
							}
							fins[x] = amp[uf.root(x)];
						}
					}
					newmp[fins] = max(newmp[fins],int(ans+bs.count()));
				}
				
			}
		}
		mp = newmp;
	}
	for (auto m : mp) {
		if (*max_element(m.first.begin(), m.first.end()) == 1) {
			finans = max(finans, m.second);
		}
	}
	if (!finans)finans = -1;
	cout << finans << endl;
	return 0;
}