这是一道经典的插头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. linux学习记录.2.hello world.c

    安装vim,指令: sudo apt-get install vim 建立一个子目录WorkSpace,指令 mkdir WorkSpace 转到该目录下,指令 cd WorkSpace 新建c文件, ...

  2. pytesser模块WindowsError错误解决方法

    在使用pytesser做图片文字识别时遇到 WindowsError: [Error 2] 错误,报错内容如下: Traceback (most recent call last): File &qu ...

  3. 64_t4

    texlive-hardwrap-svn21396.0.2-33.fc26.2.noarch.rpm 24-May-2017 15:41 35930 texlive-harmony-doc-svn15 ...

  4. .NET连接Oracle的方法

    .NET连接Oracle的方法 方式1:直接利用.NET的oracle驱动连接 引用System.data.oracleclient; using System.data.oracleclient; ...

  5. 监控MYSQL主从同步配置中监控从库运行状态的脚本

    代码如下: #!/bin/bash #Check MySQL Slave's Runnning Status #Crontab time 00:10 MYSQLPORT=`netstat -na|gr ...

  6. 详细介绍Linux finger命令的使用

    Linux 允许多个用户使用不同的终端同时登陆,Linux finger命令为系统管理员提供知道某个时候到底有多少用户在使用这台Linux主机的方法,对于这个简单的命令我们还是先介绍一下再举例吧. L ...

  7. LeetCode741. Cherry Pickup

    https://leetcode.com/problems/cherry-pickup/description/ In a N x N grid representing a field of che ...

  8. csu 1503: 点到圆弧的距离

    1503: 点到圆弧的距离 Time Limit: 1 Sec  Memory Limit: 128 MB  Special JudgeSubmit: 614  Solved: 101[Submit] ...

  9. STL中stack/queue/map以及Boost unordered_map 的使用方法

    一.stackstack 模板类的定义在<stack>头文件中.stack 模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要的,在不指定容器类型时,默认的容器类型 ...

  10. 以Docker容器方式安装Ceph

    获取Ceph的Docker镜像 因为公司对于网络环境的限制,安装ceph时使用ceph-deploy反而很不方便,且ssh免密码方式也不适用,所以使用docker方式安装. Git地址 https:/ ...