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: Time Limit Exceeded)

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<string>
#include<stack>
#include<cstdio>
#include<cmath>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef pair<int,P> P1;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define rep(i,x) for(int i=0;i<x;i++)
#define rep1(i,x) for(int i=1;i<=x;i++)
#define rrep(i,x) for(int i=x-1;i>=0;i--)
#define rrep1(i,x) for(int i=x;i>0;i--)
#define sor(v) sort(v.begin(),v.end())
#define rev(s) reverse(s.begin(),s.end())
#define lb(vec,a) lower_bound(vec.begin(),vec.end(),a)
#define ub(vec,a) upper_bound(vec.begin(),vec.end(),a)
#define uniq(vec) vec.erase(unique(vec.begin(),vec.end()),vec.end())
#define mp1(a,b,c) P1(a,P(b,c))

const int INF=1000000000;
const int dir_4[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
const int dir_8[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

const int MAX_V = 12;
struct UF{
	int par[MAX_V] , r[MAX_V];
	void init(){
		rep(i,MAX_V){
			par[i] = i;
			r[i] = 0;
		}
	}
	int find(int x){
		if(x == par[x])return x;
		return par[x] = find(par[x]);
	}
	bool same(int x,int y){
		return find(x) == find(y);
	}
	void unit(int x,int y){
		if(same(x,y))return;
		x=find(x);
		y=find(y);
		if(r[x]<r[y]){
			par[x]=y;
		}
		else {
			par[y]=x;
			if(r[x]==r[y]){
				r[x]++;
			}
		}
	}
	bool operator<(UF y) {
		rep(i,MAX_V){
			rep(j,MAX_V){
				if(y.same(i,j)){
					if(!this->same(i,j))return false;
				}
				else {
					if(this->same(i,j))return true;
				}
			}
		}
		return false;
	}
	bool operator==(UF y) {
		rep(i,MAX_V){
			rep(j,MAX_V){
				if(y.same(i,j)){
					if(!this->same(i,j))return false;
				}
				else {
					if(this->same(i,j))return false;
				}
			}
		}
		return true;
	}
};

int h,w;
struct A{
	bool black[12];
	UF uf;
	bool operator<(A y) const {
		rep(i,w){
			if(y.black[i] && (!this->black[i]))return true;
			if((!y.black[i]) && this->black[i])return false;
		}
		return y.uf < this->uf;
	}
	bool operator==(A y) const {
		rep(i,w){
			if(y.black[i] && (!this->black[i]))return false;
			if((!y.black[i]) && this->black[i])return false;
		}
		return y.uf == this->uf;
	}
};

int main(){
	map<A,P> id;
	A id_[6000];
	int memo[6000];
	scanf("%d%d",&h,&w);
	
	rep(i,(1<<w)){
		A a;
		int cnt = 0,cnt_ = 0,loc[6];
		rep(j,w)a.black[j] = (((i>>j)&1) == 1);
		rep(j,w-1)if((!a.black[j]) && (!a.black[j+1]))goto Next;
		rep(j,w){
			if(( j == 0 && a.black[0]) ||((!a.black[j-1]) && a.black[j])){
				loc[cnt++] = j;
			}
			if(a.black[j])cnt_ ++;
		}
		rep(j,(1<<((cnt*(cnt-1)))/2)){
			a.uf.init();
			rep(k,w-1)if(a.black[k] && a.black[k+1])a.uf.unit(k,k+1);
			int k = 0;
			rep(x,cnt){
				for(int y = x+1 ; y < cnt ; y ++){
					if((j>>k)&1)a.uf.unit(loc[x],loc[y]);
					k ++;
				}
			}
			if(id.find(a) == id.end()){
				id_[id.size()] = a;
				memo[id.size()] = cnt_;
				id[a] = P( id.size() , cnt_ );
			}
		}
		Next:;
	}
	
	int s = id.size();
	/*rep(i,s){
		printf("%d:",i);
		rep(j,w)printf("%d ",id_[i].black[j]?1:0);
		printf(";%d\n",memo[i]);
	}*/
	
	char c[12][12];
	rep(i,h){
		scanf("\n");
		rep(j,w){
			scanf("%c",&c[i][j]);
		}
	}
	
	int dp[2][6000];
	int t = 0 , t_ = 1;
	rep(i,6000)dp[0][i] = -INF;
	rep(i,s){
		rep(j,w){
			if(c[0][j] == '#' && (!id_[i].black[j]))goto Next1;
			if(c[0][j] == '.' && id_[i].black[j])goto Next1;
		}
		rep(j,w-1){
			if(id_[i].black[j] && id_[i].black[j+1] && !id_[i].uf.same(j,j+1))goto Next1;
		}
		dp[0][i] = memo[i];
		Next1:;
	}
		/*rep(i,s){
			printf("%d:%d\n",i,dp[t][i]);
		}puts("");*/
	rep(x,h-1){
		rep(i,6000)dp[t_][i] = -INF;
		rep(i,s){
			if(dp[t][i] == -INF)continue;
			rep(ppp,(1<<w)){
				A a,cop = id_[i];
				a.uf.init();
				rep(j,w)a.black[j] = (((ppp>>j)&1) == 1);
				rep(j,w-1)if((!a.black[j]) && (!a.black[j+1]))goto Next3;
				rep(j,w-1)if(a.black[j] && a.black[j+1])a.uf.unit(j,j+1);
				rep(j,w){
					if(c[x+1][j] == '#' && (!a.black[j]))goto Next3;
					if(c[x+1][j] == '.' && a.black[j])goto Next3;
				}
				rep(j,w)if((!a.black[j]) && (!id_[i].black[j]))goto Next3;
				rep(j,w)for(int k = j+1 ; k < w ; k ++)if(a.black[j] && id_[i].black[j] && a.black[k] && id_[i].black[k]){
					if(a.uf.same(j,k) && id_[i].uf.same(j,k))goto Next3;
				}
				rep(j,w)for(int k = j+1 ; k < w ; k ++)if(a.black[j] && id_[i].black[j] && a.black[k] && id_[i].black[k]){
					if(id_[i].uf.same(j,k))a.uf.unit(j,k);
				}
				//A cop = id_[i];
				if(!(w == 1 && x == h-2)){
					rep(j,w)if(a.black[j] && cop.black[j])cop.uf.unit(j,11);
					rep(j,w)if(cop.black[j] && (!cop.uf.same(j,11)))goto Next3;
				}
				
				/*printf("DEBUG");
				rep(j,w)printf("%d ",a.black[j]?1:0);
				puts("");
				rep(j,w){
					rep(k,w){
						printf("%d ",a.uf.same(j,k)?1:0);
					}
					puts("");
				}*/
					
				dp[t_][id[a].fr] = max ( dp[t_][id[a].fr] , dp[t][i] + id[a].sc );
				Next3:;
			}
		}
		/*rep(i,s){
			printf("%d:%d\n",i,dp[t_][i]);
		}puts("");*/
		swap(t,t_);
	}
	
	int ret = -1;
	rep(i,s){
		if(dp[t][i] == -INF)continue;
		rep(j,w)for(int k = j+1 ; k < w ; k ++){
			if(id_[i].black[j] && id_[i].black[k] && (!id_[i].uf.same(j,k)))goto Next4;
		}
		ret = max ( ret , dp[t][i] );
		Next4:;
	}
	cout << ret << endl;
}
		/*	rep(j,w){
				if(c[i][j] == '#' && (!id_[i].black[j]))goto Next2;
				if(c[i][j] == '.' && id_[i].black[j])goto Next2;
			}
			rep(j,w-1){
				if(id_[i].black[j] && id_[i].black[j+1] && !id_[i].uf.same(j,j+1))goto Next2;
			}
			dp[0][i] = cnt;
			goto Next2:;
		}*/
	
//}