通道:http://acm.timus.ru/problem.aspx?space=1&num=1519
题意:单回路,经过全部可达点,有阻碍点。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX_N = 13;
const int MAX_M = 13;
const int HASH = 10007;
const int MAX_S = 1000007;
struct node {
int head[HASH], nxt[MAX_S];
long long dp[MAX_S], st[MAX_S];
int cnt;
void init() {
memset(head, -1, sizeof head);
cnt = 0;
}
void push(long long s, long long v) {
int now = s % HASH;
for(int i = head[now]; ~i; i = nxt[i]) if(st[i] == s) {
dp[i] += v;
return ;
}
st[cnt] = s; dp[cnt] = v;
nxt[cnt] = head[now];
head[now] = cnt++;
}
}d[2];
int n, m;
int ex, ey;
int find_pos(long long s, int p) {
return (s >> (p << 1)) & 3;
}
void tp(long long &s, int p, long long v) {
s &= (~(3ll << (p << 1)));
s |= (v << (p << 1));
}
int find_r(long long s, int p) {
int cnt = 0;
for(int i = p; i <= m; ++i) {
if(find_pos(s, i) == 1) ++cnt;
else if(find_pos(s, i) == 2) --cnt;
if(!cnt) return i;
}
}
int find_l(long long s, int p) {
int cnt = 0;
for(int i = p; i >= 0; --i) {
if(find_pos(s, i) == 2) ++cnt;
else if(find_pos(s, i) == 1) --cnt;
if(!cnt) return i;
}
}
void blank(int i, int j, int cur) {
for(int k = 0; k < d[cur].cnt; ++k) {
long long t = d[cur].st[k];
int l = find_pos(t, j - 1), r = find_pos(t, j);
if(l && r) {
if(l == 1 && r == 1) {
int tpos = find_r(t, j);
tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1);
d[cur ^ 1].push(t, d[cur].dp[k]);
} else if(l == 2 && r == 1) {
tp(t, j - 1, 0); tp(t, j, 0);
d[cur ^ 1].push(t, d[cur].dp[k]);
} else if(l == 2 && r == 2) {
int tpos = find_l(t, j - 1);
tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2);
d[cur ^ 1].push(t, d[cur].dp[k]);
} else { // 最后一个非障碍格子
tp(t, j - 1, 0); tp(t, j, 0);
if (!t) if (i == ex && j == ey) d[cur ^ 1].push(t, d[cur].dp[k]);
}
} else if(l) {
if(i < n) {
d[cur ^ 1].push(t, d[cur].dp[k]);
}
if(j < m) {
tp(t, j - 1, 0); tp(t, j, l);
d[cur ^ 1].push(t, d[cur].dp[k]);
}
} else if(r) {
if(j < m) {
d[cur ^ 1].push(t, d[cur].dp[k]);
}
if(i < n) {
tp(t, j - 1, r); tp(t, j, 0);
d[cur ^ 1].push(t, d[cur].dp[k]);
}
} else { // 新建
if(i < n && j < m) {
tp(t, j - 1, 1); tp(t, j, 2);
d[cur ^ 1].push(t, d[cur].dp[k]);
}
}
}
}
void block(int i, int j, int cur) {
for (int k = 0; k < d[cur].cnt; ++k) {
long long t = d[cur].st[k];
int l = find_pos(t, j - 1), r = find_pos(t, j);
if (!l && !r) d[cur ^ 1].push(t, d[cur].dp[k]);
}
}
char str[17];
int a[MAX_N][MAX_M];
int main() {
while (2 == scanf("%d%d", &n, &m)) {
memset(a, 0, sizeof a);
ex = ey = -1;
for (int i = 1; i <= n; ++i) {
scanf("%s", str + 1);
for (int j = 1; j <= m; ++j) {
if (str[j] == '.') {
a[i][j] = 1;
ex = i, ey = j;
}
}
}
if (ex == -1) puts("0");
else {
int cur = 0;
d[cur].init();
d[cur].push(0, 1);
long long ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
d[cur ^ 1].init();
if (a[i][j]) blank(i, j, cur);
else block(i, j, cur);
cur ^= 1;
}
for(int k = 0; k < d[cur].cnt; ++k) {
d[cur].st[k] <<= 2;
}
}
for (int i = 0; i < d[cur].cnt; ++i)
ans += d[cur].dp[i];
printf("%I64d\n", ans);
}
}
return 0;
}