[URAL 1519] Formula 1 轮廓线DP 括号序列

题意

  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 }
时间: 2024-07-29 15:44:00

[URAL 1519] Formula 1 轮廓线DP 括号序列的相关文章

【bzoj1814】Ural 1519 Formula 1 插头dp

题目描述 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数. 输入 The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop)

bzoj 1814: Ural 1519 Formula 1 插头dp经典题

用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 199917 6 #define ll long long 7 #define bp 1<<bit[j-1] 8 #define bq 1<<bit[j] 9 using nam

bzoj1814: Ural 1519 Formula 1 2011-12-20

1814: Ural 1519 Formula 1Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 263  Solved: 70[Submit][Status][Discuss]DescriptionRegardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well- known, that the 

【URAL 1519】【插头dp模板】Formula 1

1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well-known, that the city will conduct one of the Formula 1 events. Surely

URAL 1519 Formula 1 (插头DP,常规)

题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法? 思路: 本来是很基础的题,顿时不知道进入了哪个坑.这篇插头DP的文章够详细,推荐一看(最好不要照抄代码). 细节要小心,比如输出用I64d,必须用long long,判断是否无哈密顿回路,位操作等等. 这次仍然用括号表示法,1表示(,2表示). 1 #include <bits/stdc++.h> 2 #define pii pair<int,int&g

bzoj 1814: Ural 1519 Formula 1【插头dp】

设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数 括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合 下面的蓝线是黄色格子的轮廓线,dp转移要把它转到橙色轮廓线,设已经在状压的s中取到两条边的状态记为b1,b2 然后分很多情况讨论: (i,j)是障碍:那就只能什么都不放的转移,也就是只能从b1=0,b2=0转移到新轮廓线的b1=0,b2=0 if(!a[i][j]) { if(!b1&&!b2) add(x,v); } b1=0,b2

【插头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 in

URAL - 1519 Formula 1 (插头DP)

这里写链接内容 刚开始学插头dp好吃力,看了别人的代码有点看不懂,所以就参考了别人的代码,写了注释,希望有帮助 如果看不懂可以问 //下面所说的情况全在论文中的第13页 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 13 #define S1 14000 #define S2 1600000 struct Queue{ int opt; long

bzoj1814: Ural 1519 Formula 1 动态规划 插头dp

dbzoj依然爆炸 题目描述 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数. 输入 The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (f