这里是完整代码,有注释(虽然说感觉还是不是很完整啊)
#include <bits/stdc++.h>
using namespace std;
const int N = 14;
const int mod = 4001;
int n, m, endx, endy;
int now, last;
long long ans;
bool a[N][N];
int head[mod + 5], nxt[2 << 24], que[2][2 << 24], cnt[2], inc[N];
long long val[2][2 << 24];
char s[101];
inline void init ()
{
scanf ("%d %d", &n, &m);
for (int i = 1; i <= n; i ++)
{
scanf ("%s", s + 1);
for (int j = 1; j <= m; j ++)
if (s[j] == '.')
{
a[i][j] = 1;
endx = i;
endy = j;
}
}
inc[0] = 1;
for (int i = 1; i <= 13; i ++)
inc[i] = inc[i - 1] << 2;
}
inline void insert (int bit, long long num)
{
int u = bit % mod + 1;
for (int i = head[u]; i; i = nxt[i])
if (que[now][i] == bit)
{
val[now][i] += num;
return ;
}
nxt[++ cnt[now]] = head[u]; // 这里采用挂表法
head[u] = cnt[now]; // 诶是不是和前向星很像
que[now][cnt[now]] = bit;
val[now][cnt[now]] = num;
}
inline void work ()
{
cnt[now] = 1; // hash 末指针
val[now][1] = 1; // 记录状态值
que[now][1] = 0; // 队列记录状态
// last = 1;
// insert (0, 1);
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= cnt[now]; j ++)
que[now][j] <<= 2;
// 到每行第一个格子时在前面补一个空插头,剩下的部分从上一行最后一个格子那里直接搬过来
for (int j = 1; j <= m; j ++)
{
memset (head, 0, sizeof (head)); // 清空 hash
last = now;
now ^= 1;
cnt[now] = 0; // 清空 hash
for (int k = 1; k <= cnt[last]; k ++) // 枚举所有状态
{
long long bit = que[last][k], num = val[last][k]; // 获取当前状态
int p = (bit >> ((j - 1) * 2)) % 4, q = (bit >> (j * 2)) % 4;
if (!a[i][j]) // 当前点有障碍
if (!p && !q)
insert (bit, num);
else if (!p && !q) // 无右插头,无下插头
if (a[i + 1][j] && a[i][j + 1]) // 左,上无障碍
insert (bit + inc[j - 1] + (inc[j] << 1), num); // 添加一个连通分量
else if (!p && q) // 无右插头,有下插头,情况三
{
if (a[i][j + 1]) // 左无障碍
insert (bit, num);
if (a[i + 1][j]) // 上无障碍
insert (bit - inc[j] * q + inc[j - 1] * q, num);
}
else if (p && !q) // 有右插头,无下插头,情况三
{
if (a[i + 1][j]) // 上无障碍
insert (bit, num);
if (a[i][j + 1]) // 左无障碍
insert (bit - inc[j - 1] * p + inc[j] * p, num);
}
// 有右插头,有下插头,情况二
else if (p == 1 && q == 1) // 情况 2 - 1
{
int k1 = 1;
for (int l = j + 1; l <= m; l ++)
{
if ((bit >> (l * 2)) % 4 == 1)
k1 ++;
if ((bit >> (l * 2)) % 4 == 2)
k1 --;
if (!k1)
{
insert (bit - inc[j] - inc[j - 1] - inc[l], num);
break;
}
}
}
else if (p == 2 && q == 2) // 情况 2 - 2
{
int k1 = 1;
for (int l = j - 2; l >= 0; l --)
{
if ((bit >> (l * 2)) % 4 == 1)
k1 --;
if ((bit >> (l * 2)) % 4 == 2)
k1 ++;
if (!k1)
{
insert (bit - (inc[j] << 1) - (inc[j - 1] << 1) + inc[l], num);
break;
}
}
}
else if (p == 2 && q == 1) // 情况 2 - 4
insert (bit - (inc[j - 1] << 1) - inc[j], num);
else if (i == endx && j == endy) // 情况 2 - 3
ans += num;
}
}
}
}
int main ()
{
init ();
work ();
printf ("%lld", ans);
}