【插头DP】URAL 1519 Formula 1
通道: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; }