按格插头DP
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 25
using namespace std;
typedef long long ll;
int n, m, Endx, Endy;
const int mod = 997;
const int N = 1000010;
struct hashmap{
int h[mod],nxt[N],size;
ll f[N],st[N];
void init(){
memset(h, 0, sizeof h);
size = 0;
}
void push(ll val,ll ans){
int now = val % mod;
for(int i = h[now]; i;i = nxt[i])
if(st[i] == val){
f[i] += ans;
return;
}
++size;
f[size] = ans;
st[size] = val;
nxt[size] = h[now];
h[now] = size;
}
}dp[2];
bool map[maxn][maxn];
int code[maxn], ch[maxn];
void Decode(ll st){
for(int i = m;i >= 0;i --){
code[i] = st & 7;
st >>= 3;
}
}
ll Encode(){
ll st = 0;
int cnt = 0;
memset(ch, -1, sizeof ch);
ch[0] = 0;
for(int i = 0;i <= m;i ++){
if(ch[code[i]] == -1)
ch[code[i]] = ++cnt;
code[i] = ch[code[i]];
st <<= 3;
st |= code[i];
}
return st;
}
void Shift(){
for(int i = m;i > 0;i --)
code[i] = code[i - 1];
code[0] = 0;
}
void DP(int i, int j, int cur, bool type){
if(type == 0){
for(int k = 1;k <= dp[cur].size;k ++){
Decode(dp[cur].st[k]);
code[j] = code[j - 1] = 0;
if(j == m)Shift();
dp[cur ^ 1].push(Encode(), dp[cur].f[k]);
}
return;
}
for(int k = 1;k <= dp[cur].size;k ++){
Decode(dp[cur].st[k]);
int Left = code[j - 1],Up = code[j];
if(Left && Up){
if(Left == Up){
if(Endx == i && Endy == j){
code[j] = code[j - 1] = 0;
if(j == m)Shift();
dp[cur ^ 1].push(Encode(),dp[cur].f[k]);
}
}
else{
code[j] = code[j - 1] = 0;
for(int i = 0;i <= m;i ++)
if(code[i] == Up)
code[i] = Left;
if(j == m)Shift();
dp[cur ^ 1].push(Encode(),dp[cur].f[k]);
}
}
else if((Left == 0 && Up)||(Up == 0 && Left)){
int tmp = Left == 0 ? Up : Left;
if(map[i][j + 1]){
code[j - 1] = 0;
code[j] = tmp;
if(j == m)Shift();
dp[cur ^ 1].push(Encode(),dp[cur].f[k]);
}
if(map[i + 1][j]){
code[j - 1] = tmp;
code[j] = 0;
if(j == m)Shift();
dp[cur ^ 1].push(Encode(),dp[cur].f[k]);
}
}
else{
if(map[i][j + 1] && map[i + 1][j]){
code[j - 1] = code[j] = 15;
dp[cur ^ 1].push(Encode(),dp[cur].f[k]);
}
}
}
}
int main(){
freopen("formula1.in", "r", stdin);
freopen("formula1.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++){
char QAQ = getchar();
for(;QAQ < '!';QAQ = getchar());
if(QAQ == '.'){
map[i][j] = true;
Endx = i;
Endy = j;
}
}
if(Endx == 0){
printf("0\n");
return 0;
}
int cur = 0;
ll ans = 0;
dp[cur].init();
dp[cur].push(0, 1);
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= m;j ++){
dp[cur ^ 1].init();
DP(i, j, cur, map[i][j]);
cur ^= 1;
}
for(int i = 1;i <= dp[cur].size;i ++)
ans += dp[cur].f[i];
printf("%lld\n",ans);
return 0;
}