Problem:
Problem E : Connect

r × c のグリッドが与えられる。

グリッドのいくつかのマスには1から8までの数字が書かれている。

数字が書かれているマスと他の数字が書かれているマスを線で結ぶ必要がある。

数字が書かれているマスについて、そのマスに書かれている本数だけ、他のマスとの間に線を結ぶ必要がある。

ただし、線を結べるのは上下左右方向だけで、一つの方向について、最大２本までである。

他の数字を跨いで線で結ぶことはできない。

また、次のように交差してしまう結び方をすることはできない。

グリッドが入力として与えられるので、数字が書かれているマス全てを正しく結ぶ方法が、何通りあるのかを数えて欲しい。

Input

入力は以下のフォーマットで与えられる。

r c
grid1
.
.
.
gridr-1

gridi は長さcの文字列で、1から8までの数字か"."からなる。

入力は以下の制約を満たす

1 ≤ r,c ≤ 10

Output

答えの値を100,000,007で割った余りを1行に出力せよ

Sample Input 1

3 3
.1.
1.1
.1.

Sample Output 1

0

Sample Input 2

1 3
1.1

Sample Output 2

1

Sample Input 3

3 3
4.2
...
2..

Sample Output 3

1

Sample Input 4

7 7
2.3.1.1
.......
2......
.......
..3.3..
.......
2.2.4.3

Sample Output 4

10

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

#include <iostream>
#include <vector>
#include <string>
#include <cstring>

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define MEMSET(v, s) memset(v, s, sizeof(v))

using namespace std;

vector<string> v;
const int MOD = 1e8 + 7;
int dp[10][10][60000][3];
int R, C;
int thr[11];

inline int get(int x, int pos){
	return x / thr[pos] % 3;
}

inline int ins(int x, int pos, int val){
	return x + (val - get(x, pos))*thr[pos];
}

int rec(int r, int c, int x, int left){
	if (r == R) return !x;
	if (c == C) return left?0:rec(r + 1, 0, x, 0);

	int &res = dp[r][c][x][left];
	if (res >= 0) return res;

	res = 0;
	if (v[r][c] == '.'){
		if (!(get(x, c) && left)) res = rec(r, c + 1, x, left);
	}
	else{
		int rest = v[r][c] - '0';
		rest -= get(x, c) + left;
		rep(right, 3){
			rep(down, 3){
				if (right + down != rest) continue;
				res += rec(r, c + 1, ins(x, c, down), right);
				res %= MOD;
			}
		}
	}

	return res;
}

int main(){
	thr[0] = 1;
	FOR(i, 1, 11) thr[i] = thr[i - 1] * 3;

	cin >> R >> C;
	v.resize(R);
	rep(i, R) cin >> v[i];

	MEMSET(dp, -1);
	cout << rec(0, 0, 0, 0) << endl;

	return 0;
}