这是一道经典的插头DP单回路模板题。

  用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制。

  1、当同时存在左、上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连;若不相同,则把这两个连通块连起来。

  2、如果只存在左或上插头的时候,则要延续连通块。

  3、若都不存在左和上插头的时候,就要新建一个连通块。

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm> using namespace std; #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define DWN(i, a, b) for (int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define mset(a, b) memset(a, b, sizeof(a))
typedef long long LL;
const int MAXD = , HASH = , STATE = ;
int n, m, maze[MAXD][MAXD], code[MAXD], ch[MAXD], end_x, end_y;
char str[MAXD];
struct HASHMAP
{
int head[HASH], nxt[STATE], siz; LL f[STATE], state[STATE];
void clear() { siz = , mset(head, -); }
void push(LL x, LL add)
{
int pos = x%HASH, i = head[pos];
for (; i != -; i = nxt[i])
if (state[i] == x) { f[i] += add; return ; }
state[siz] = x, f[siz] = add;
nxt[siz] = head[pos], head[pos] = siz++;
}
}hm[]; void in()
{
scanf("%d %d", &n, &m), mset(maze, ), end_x = end_y = -;
REP(i, , n)
{
scanf("%s", str+);
REP(j, , m)
if (str[j] == '.')
maze[i][j] = , end_x = i, end_y = j;
}
} void decode(LL x)
{
REP(i, , m) code[i] = x&, x >>= ;
} LL encode()
{
LL ret = ; int cnt = ;
mset(ch, -), ch[] = ;
DWN(i, m, )
{
if (ch[code[i]] == -) ch[code[i]] = ++cnt;
ret <<= , ret |= ch[code[i]];
}
return ret;
} void shift(int j)
{
if (j != m) return ;
DWN(i, m, ) code[i] = code[i-];
code[] = ;
} void dp_blank(int i, int j, int cur)
{
REP(k, , hm[cur].siz-)
{
decode(hm[cur].state[k]);
int lef = code[j-], up = code[j];
if (lef && up)
{
if (lef == up && !(i == end_x && j == end_y)) continue ;
REP(t, , m)
if (code[t] == up) code[t] = lef;
code[j-] = code[j] = , shift(j);
hm[cur^].push(encode(), hm[cur].f[k]);
}
else
if (lef || up)
{
int t = lef ? lef : up;
if (maze[i][j+])
{
code[j-] = , code[j] = t;
hm[cur^].push(encode(), hm[cur].f[k]);
}
if (maze[i+][j])
{
code[j-] = t, code[j] = , shift(j);
hm[cur^].push(encode(), hm[cur].f[k]);
}
}
else
if (maze[i][j+] && maze[i+][j])
{
code[j-] = code[j] = , shift(j);
hm[cur^].push(encode(), hm[cur].f[k]);
}
}
} void dp_block(int i, int j, int cur)
{
REP(k, , hm[cur].siz-)
{
decode(hm[cur].state[k]), shift(j);
hm[cur^].push(encode(), hm[cur].f[k]);
}
} void work()
{
int cur = ; LL ans = ;
hm[].clear(), hm[].clear(), hm[cur].push(, );
REP(i, , n)
REP(j, , m)
{
if (maze[i][j]) dp_blank(i, j, cur);
else dp_block(i, j, cur);
hm[cur].clear(), cur ^= ;
}
REP(i, , hm[cur].siz-) ans += hm[cur].f[i];
printf("%I64d\n", ans);
} int main()
{
in();
work();
return ;
}

Ural 1519 Formula 1 插头DP的更多相关文章

  1. 【BZOJ1814】Ural 1519 Formula 1 插头DP

    [BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...

  2. bzoj1814 Ural 1519 Formula 1(插头dp模板题)

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 924  Solved: 351[Submit][Sta ...

  3. bzoj 1814 Ural 1519 Formula 1 插头DP

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 942  Solved: 356[Submit][Sta ...

  4. bzoj 1814 Ural 1519 Formula 1 ——插头DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1814 普通的插头 DP .但是调了很久.注意如果合并两个 1 的话,不是 “把向右第一个 2 ...

  5. BZOJ1814: Ural 1519 Formula 1(插头Dp)

    Description Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic gam ...

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

    用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. #include<iostream> #include<cstdio> #include<cstr ...

  7. 【Ural】1519. Formula 1 插头DP

    [题目]1519. Formula 1 [题意]给定n*m个方格图,有一些障碍格,求非障碍格的哈密顿回路数量.n,m<=12. [算法]插头DP [题解]<基于连通性状态压缩的动态规划问题 ...

  8. 【BZOJ1814】Ural 1519 Formula 1 (插头dp)

    [BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...

  9. ural 1519 Formula 1(插头dp)

    1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...

随机推荐

  1. Entity Framework(EF的Database First方法)

    EntityFramework,是Microsoft的一款ORM(Object-Relation-Mapping)框架.同其它ORM(如,NHibernate,Hibernate)一样, 一是为了使开 ...

  2. 关于servlet中重定向、转发的地址问题

    先写一个正斜杠"/",再判断是服务器使用该地址还是网站使用该地址. 访问网络资源用/,访问硬盘资源用\. 例如: 转发:      request.getRequestDispat ...

  3. java反序列化漏洞

    http://www.freebuf.com/vuls/86566.html 有时间了  仔细阅读

  4. Ubuntu 14.04 64位上安装wps office软件(转http://m.blog.csdn.net/blog/yhc13429826359/24179933)

    废话少说,只给出方法供各位参考!wps for Linux版本已经有两三年没有大的动作,当然其他平台,比如windows,Android,ios上的wps效果还是很赞的说. 下面是我成功安装的步骤: ...

  5. MySQL登录问题1045 (28000)处理步骤【原创】

    MySQL登录问题1045 (28000)  俩台服务器主从复制,从的同步账号无法远程登录主服务器.报错ERROR 1045 (28000): Access denied for user 'root ...

  6. 190.Reverse Bits---位运算

    题目链接:https://leetcode.com/problems/reverse-bits/description/ 题目大意:将数值的二进制反转. 法一(借鉴):由于是无符号32位整型,当二进制 ...

  7. Petrozavodsk Summer Training Camp 2017

    Petrozavodsk Summer Training Camp 2017 Problem A. Connectivity 题目描述:有\(n\)个点,现不断地加边.每条边有一种颜色,如果一个点对\ ...

  8. shell脚本执行方式

    # BY THE WAY, 其实这块内容算是比较简单的,但是都比较常记得它最基本的两种方式,另外两种却忘记了 1. 利用sh或bash命令执行 sh test.sh bash test.sh 2. 在 ...

  9. Nginx源码分析--epoll模块

    Nginx采用epoll模块实现高并发的网络编程,现在对Nginx的epoll模块进行分析. 定义在src/event/modules/ngx_epoll_module.c中 1. epoll_cre ...

  10. redis aof文件过大问题

    http://www.itnose.net/detail/6682725.html 最近新安装了一台redis,版本为redis-3.2.5 数据盘用的是固态硬盘. 之前用的是普通硬盘,redis日志 ...