Cdq的论文,这个人人皆知。但是她的那个ppt里状态转移很多地方说的不是很明白,结果弄了好久才弄明白。zero有份“很珍贵”的doc版论文,据说里面说的很清楚。。。 目前只做了简单3进制的回路问题 自我感觉PPT里没提到的几点: 1、分量合并的时候,还有一种情况是( ))变为)# # 2、分量合并的时候,比如( ))这种,左面那个(不一定是紧挨着{dy}个)的 3、()变成##,仅在{zh1}一格,这个不看不知道啊。。。 为什么要用hash?可不可以不用hash? 因为3进制的话,很多状态都是不合法的,在3^13里面合法状态只有4w多一点。想到什么了?unsigned short!对于HOJ1712,合法状态不超过6k,short就够了。 不过事实证明枚举合法状态没有hash来的快,可能是因为数组太大,取数的时候效率低的缘故 3进制还是4进制? 4进制可以位运算提高速度,但是相当卡内存,必须配合上述只枚举合法状态的方法。不过代码写出来不是很好看。。。 鉴于以后的4进制哈密顿路,5进制普通路,以及多进制联通块问题,还是留个3进制的模板吧。 PS:wa一晚上加一上午发现URAL是用I64d的。。。 URAL1519: #include<iostream> #include<cstdio> #include<cstring> using namespace std; char g[17][17]; #define For(i,n) for(i=0;i<(n);i++) #define f5(s) dp[t][s]=dp[t][s]==-1?dp[p][kk]:dp[t][s]+dp[p][kk] long long dp[2][42000], ans; int dig[15] = {1}, tot = 0, t, p, ansx, ansy; unsigned short ts[1600000]; int st[42000]; bool check(int num) { int cnt = 0; while (num) { int k = num % 3; if (k == 1) cnt++; if (k == 2) cnt--; num /= 3; if (cnt < 0) return false; } if (cnt != 0) return false; return true; } int getbit(int k, int j) { while (j-- > 0) { k /= 3; } return k % 3; } int main() { int i, j, n, m, k, kk; for (i = 1; i < 15; i++) dig[i] = dig[i - 1]*3; For(i, dig[13]) { if (check(i)) { ts[i] = tot; st[tot++] = i; } else ts[i] = 50000; } st[tot++] = 999999999; scanf("%d%d", &n, &m); ans = 0; For(i, n) { scanf("\n%s", g[i]); For(j, m) if (g[i][j] == '.') ansx = i, ansy = j; } memset(dp, -1, sizeof (dp)); dp[t = 0][0] = 1; For(i, n) { For(j, m) { t ^= 1, p = 1 - t; memset(dp[t], -1, sizeof (dp[t])); for (kk = 0; (k = st[kk]) < dig[m + 1]; kk++) { if (dp[p][kk] != -1) { int l = getbit(k, j); int u = getbit(k, j + 1); int pre = k - l * dig[j] - u * dig[j + 1]; if (g[i][j] != '.') { if (l == 0 && u == 0) f5(kk); continue; } if (l == 0 && u == 0&&g[i+1][j] == '.'&&g[i][j+1] == '.') f5(ts[pre + 1 * dig[j] + 2 * dig[j + 1]]); if (l + u == 3) { if (l == 1 && u == 2) { if (i == ansx && j == ansy&&pre==0) { ans += dp[p][kk]; } continue; } f5(ts[pre]); } if ((l != 0 && u == 0) || (l == 0 && u != 0)) { if (g[i+1][j]=='.') f5(ts[pre + (u + l) * dig[j]]); if (g[i][j+1]=='.')f5(ts[pre + (u + l) * dig[j + 1]]); } if (l == 1 && u == 1) { int cnt = 1; for (int jj = j + 2; jj < m + 1; jj++) { int e = getbit(k, jj); if (e == 2) cnt--; if (e == 1) cnt++; if (cnt == 0) { f5(ts[pre - 2 * dig[jj] + 1 * dig[jj]]); break; } } } if (l == 2 && u == 2) { int cnt = 1; for (int jj = j - 1; jj >= 0; jj--) { int e = getbit(k, jj); if (e == 1) cnt--; if (e == 2) cnt++; if (cnt == 0) { f5(ts[pre - 1 * dig[jj] + 2 * dig[jj]] ); break; } } } } } } t ^= 1, p = 1 - t; memset(dp[t], -1, sizeof (dp[t])); for (kk = 0; (k = st[kk]) < dig[m]; kk++) { j = k * 3; dp[t][ts[j]] = dp[p][kk]; } } printf("%I64d\n", ans); }
|