1. 程式人生 > >[URAL 1519] Formula 1 輪廓線DP 括號序列

[URAL 1519] Formula 1 輪廓線DP 括號序列

tdi 輪廓線 col oid ring strong else can har

題意

  n * m 的矩形, 有壞點, 問哈密頓回路數量.

  n, m <= 11 .

分析

1. 確立狀態

  我們考慮輪廓線DP.

  為此, 我們要刻畫量化輪廓線的相關信息:

    ① 插頭是否存在?

    ② 插頭的連通性.

  我們發現: 插頭一一對應, 且互不相交. 於是考慮使用括號序列刻畫輪廓線.

  至於量化, 我們將一個括號序列當做一個三進制數即可.

2. 轉移

  從上一行的最後一個, 轉移到當前行的第一個: 位移.

  當前格子為壞點: 對於沒有插頭插到當前點的狀態原樣復制.

  否則:

  (1) L = # , R = #

  技術分享

  (2) L = ( , U = (

  技術分享

  (3) L = ) , U = )

  技術分享

  (4) L = ) , U = (

  技術分享

  (5) L = ), U = (

    只能出現在棋盤的最後一格.

  (6) (L != #) ^ (U != #)

    兩種轉移方式均可.

實現

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cctype>
 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
 6
#define LL long long 7 8 const int N = 15; 9 const int B = 1600000; 10 const int Z = 50000; 11 12 int n, m, Lx, Ly; char s[N][N]; 13 14 #define pos(x) (Dec[s] / Pow[x-1] % 3) 15 int Pow[N], Enc[B], Dec[Z], tot; 16 inline bool Legal(int s) { 17 int cnt = 0; 18 F(i, 0, m) { 19 int key = s / Pow[i] % 3
; 20 if (key == 1) cnt++; 21 else if (key == 2) { if (!cnt--) return false; } 22 } 23 return !cnt; 24 } 25 void Hash(void) { 26 Pow[0] = 1; F(i, 1, m+1) Pow[i] = Pow[i-1] * 3; 27 F(s, 0, Pow[m+1]-1) 28 if (Legal(s)) Enc[s] = ++tot, Dec[tot] = s; 29 } 30 31 LL f[Z], g[Z]; 32 33 int main(void) { 34 #ifndef ONLINE_JUDGE 35 freopen("ural1519.in", "r", stdin); 36 #endif 37 38 scanf("%d %d", &n, &m); F(i, 1, n) scanf("%s", s[i]+1); 39 F(i, 1, n) F(j, 1, m) if (s[i][j] == .) Lx = i, Ly = j; 40 41 Hash(); 42 43 F(i, 1, n) { 44 if (i == 1) f[Enc[0]] = 1; 45 else { 46 memset(g, 0, sizeof g); 47 F(s, 1, tot) 48 if (Dec[s] < Pow[m]) 49 g[Enc[Dec[s] * 3]] = f[s]; 50 g[0] = 0, memcpy(f, g, sizeof g); 51 } 52 53 F(j, 1, m) { 54 memset(g, 0, sizeof g); 55 if (s[i][j] == *) { 56 F(s, 1, tot) 57 g[s] = !pos(j) && !pos(j+1) ? f[s] : 0; 58 } 59 else { 60 F(s, 1, tot) if (f[s] != 0) { 61 int S1 = pos(j), S2 = pos(j+1); 62 if (!S1 && !S2) 63 g[Enc[Dec[s] + Pow[j-1] + 2 * Pow[j]]] += f[s]; 64 else if (!S1 ^ !S2) { 65 g[s] += f[s]; 66 g[Enc[Dec[s] + (S2 - S1) * Pow[j-1] + (S1 - S2) * Pow[j]]] += f[s]; 67 } 68 else if (S1 == 1 && S2 == 2) { 69 if (Lx == i && Ly == j) 70 g[Enc[Dec[s] - Pow[j-1] - 2 * Pow[j]]] += f[s]; 71 } 72 else if (S1 == 2 && S2 == 1) 73 g[Enc[Dec[s] - 2 * Pow[j-1] - Pow[j]]] += f[s]; 74 else if (S1 == 1 && S2 == 1) { 75 int cnt = 1, id = j+1; 76 for (id++; ; id++) 77 if (pos(id) == 1) cnt++; 78 else if (pos(id) == 2) { if (!--cnt) break; } 79 g[Enc[Dec[s] - Pow[j-1] - Pow[j] - Pow[id-1]]] += f[s]; 80 } 81 else { 82 int cnt = -1, id = j; 83 for (id--; ; id--) 84 if (pos(id) == 2) cnt--; 85 else if (pos(id) == 1) { if (!++cnt) break; } 86 g[Enc[Dec[s] - 2 * Pow[j-1] - 2 * Pow[j] + Pow[id-1]]] += f[s]; 87 } 88 } 89 } 90 g[0] = 0, memcpy(f, g, sizeof g); 91 } 92 } 93 printf("%lld\n", f[Enc[0]]); 94 95 return 0; 96 }

[URAL 1519] Formula 1 輪廓線DP 括號序列