AtCoder problem 023

C++ solution:
#include <iostream>

#include <string>

#include <map>

using namespace std;



// Input

int H, W;

char c[25][25];



// Map

int cnt[25];

bool used[25][25];

int nex0[25][1 << 18];

int nex1[25][1 << 18];

int state[25][1 << 18];

map<int, pair<int, bool>> Map[25];



// DP

int mod = 1000000007;

int dp[25][25][1 << 18];



bool hantei(int sx, int sy) {

	int dx[8] = { 1, 1, 1, 0, -1, -1, -1, 0 };

	int dy[8] = { -1, 0, 1, 1, 1, 0, -1, -1 };

	for (int i = 0; i < 8; i++) {

		int tx = sx + dx[i], ty = sy + dy[i];

		if (tx < 0 || ty < 0 || ty >= W) continue;

		if (used[tx][ty] == true) return false;

	}

	return true;

}



void dfs(int pos, int dep, int str) {

	int sx = pos / W, sy = pos % W;

	if (dep == W + 1) {

		int idx = cnt[sy];

		bool flag = hantei(sx, sy);

		state[sy][idx] = str;

		Map[sy][str] = make_pair(idx, flag);

		cnt[sy] += 1;

		return;

	}



	dfs(pos + 1, dep + 1, str);

	if (hantei(sx, sy) == true) {

		used[sx][sy] = true;

		dfs(pos + 1, dep + 1, str + (1 << dep));

		used[sx][sy] = false;

	}

}



int main() {

	// Step #1. Input

	cin >> H >> W;

	for (int i = 0; i < H; i++) {

		for (int j = 0; j < W; j++) cin >> c[i][j];

	}



	// Step #2. Initialize

	for (int i = 0; i < W; i++) {

		dfs(i, 0, 0);

	}

	for (int i = 0; i < W; i++) {

		for (int j = 0; j < cnt[i]; j++) {

			int t = state[i][j];

			int t0 = (t >> 1);

			int t1 = (t >> 1) + (1 << W);

			nex0[i][j] = Map[(i + 1) % W][t0].first;

			if (Map[i][t].second == true) {

				nex1[i][j] = Map[(i + 1) % W][t1].first;

			}

			else {

				nex1[i][j] = -1;

			}

		}

	}



	// Step #3. DP

	dp[0][0][0] = 1;

	for (int i = 0; i < H; i++) {

		for (int j = 0; j < W; j++) {

			int n1 = i, n2 = j + 1;

			if (n2 == W) { n1 += 1; n2 = 0; }



			for (int k = 0; k < cnt[j]; k++) {

				if (dp[i][j][k] == 0) continue;

				dp[n1][n2][nex0[j][k]] += dp[i][j][k];

				dp[n1][n2][nex0[j][k]] %= mod;

				if (nex1[j][k] != -1 && c[i][j] == '.') {

					dp[n1][n2][nex1[j][k]] += dp[i][j][k];

					dp[n1][n2][nex1[j][k]] %= mod;

				}

			}

		}

	}



	// Step #4. Output The Answer

	int Answer = 0;

	for (int i = 0; i < cnt[0]; i++) {

		Answer += dp[H][0][i];

		Answer %= mod;

	}

	cout << Answer << endl;

	return 0;

}

Crystal solution: MOD = 10**9 + 7
h, w = read_line.split.map(&.to_i)
grid = (1..h).map { read_line }

a = (1..w).reduce([[0], [1], [] of Int32, [] of Int32]) { |(a00, a01, a10, a11), _|
  b00 = (a00 + a01).map { |x| x << 1 }
  b01 = a00.map { |x| x << 1 | 1 }
  b10 = (a10 + a11).map { |x| x << 1 }
  b11 = (a01 + a10).map { |x| x << 1 | 1 }
  [b00, b01, b10, b11]
}.flatten
m = a.size

hash = a.zip(0..).to_h
next1 = a.map { |bit| hash[bit >> 1] }
next2 = a.map { |bit| hash[bit >> 1 | 1 << w]? }

dp = [1] + [0] * m.pred
(0...h).each do |i|
  (0...w).each do |j|
    dp = (0...m).each_with_object([0] * m) do |k, dp2|
      next if dp[k] == 0
      bit = a[k]
      dp2[n1 = next1[k]] = (dp2[n1] + dp[k]) % MOD
      unless grid[i][j] == '#' ||
             (i != 0 && j != 0 && bit.bit(0) == 1) ||
             (i != 0 && bit.bit(1) == 1) ||
             (i != 0 && j != w - 1 && bit.bit(2) == 1) ||
             (j != 0 && bit.bit(w) == 1)
        dp2[n2 = next2[k].not_nil!] = (dp2[n2] + dp[k]) % MOD
      end
    end
  end
end
puts dp.reduce(0) { |sum, x| (sum + x) % MOD }