P5056 【模板】插头dp
\(\color{#0066ff}{ 题目描述 }\)
给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路。问有多少种铺法?
\(\color{#0066ff}{输入格式}\)
第1行,n,m(2<=n,m<=12)
从第2行到第n+1行,每行一段字符串(m个字符),"*"表不能铺线,"."表必须铺
\(\color{#0066ff}{输出格式}\)
输出一个整数,表示总方案数
\(\color{#0066ff}{输入样例}\)
4 4
**..
....
....
....
\(\color{#0066ff}{输出样例}\)
2
\(\color{#0066ff}{数据范围与提示}\)
none
\(\color{#0066ff}{ 题解 }\)
插头DP本来以为多niubility的算法原来本质还是个DP,就是情况多了点qwq
状压分割线,有三种情况,无,左插头,右插头(详见洛谷题解懒得写了)
只要明白状态分析出所有情况即可
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
std::unordered_map<LL, LL> f[2];
//我TM就不写hash表
int n, m, s, t;
bool mp[100][100];
char getch() {
char ch = getchar();
while(ch != '*' && ch != '.') ch = getchar();
return ch;
}
void init() {
n = in(), m = in();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
mp[i][j] = getch() == '.';
if(mp[i][j]) s = i, t = j;
}
}
LL pos(int v, int x) { return (v << (x << 1)); }
//返回第x大块的v状态(两个二进制来状压)
LL work() {
int now = 0, nxt = 1;
f[0][0] = 1;
LL U = (1LL << ((m + 1) << 1)) - 1;
//全集
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
f[nxt].clear();
for(auto &k:f[now]) {
LL S = k.first, val = k.second;
LL L = (S >> ((j - 1) << 1)) & 3, R = (S >> (j << 1)) & 3;
//分割线(L是当前竖着的那个,R是紧接着横着的那个)
if(!mp[i][j]) {
if(!L && !R) f[nxt][S] += val;
continue;
}
// 0 0
if(!L && !R) {
if(mp[i][j + 1] && mp[i + 1][j]) f[nxt][S ^ pos(1, j - 1) ^ pos(2, j)] += val;
//0 0 -> 1 2
}
//2 1
else if(L == 2 && R == 1) {
//2 1 -> 0 0
f[nxt][S ^ pos(L, j - 1) ^ pos(R, j)] += val;
}
// 0 1 // 1 0 // 0 2 // 2 0
else if(!L || !R) {
//0 1 // 0 2
if(!L) {
//拐弯
if(mp[i][j + 1]) f[nxt][S] += val;
//不拐弯
if(mp[i + 1][j]) f[nxt][S ^ pos(L, j - 1) ^ pos(L, j) ^ pos(R, j - 1) ^ pos(R, j)] += val;
}
//同上
else if(!R) {
if(mp[i][j + 1]) f[nxt][S ^ pos(L, j - 1) ^ pos(L, j) ^ pos(R, j - 1) ^ pos(R, j)] += val;
if(mp[i + 1][j]) f[nxt][S] += val;
}
}
//1 1 // 2 2
else if(L == R) {
// 1 1
if(L == 1) {
int du = 0;
//1 1 -> 0 0 但是源头接口处右插头变成左插头
for(int p = j; ; p++) {
LL o = (S >> (p << 1)) & 3;
if(o == 1) du++;
if(o == 2) du--;
if(!du) {
//原来状态消去,弄上新状态
f[nxt][S ^ pos(L, j - 1) ^ pos(R, j) ^ pos(2, p) ^ pos(1, p)] += val;
break;
}
}
}
//根上面差不多
else if(L == 2) {
int du = 0;
for(int p = j - 1; ; p--) {
LL o = (S >> (p << 1)) & 3;
if(o == 1) du--;
if(o == 2) du++;
if(!du) {
f[nxt][S ^ pos(L, j - 1) ^ pos(R, j) ^ pos(2, p) ^ pos(1, p)] += val;
break;
}
}
}
}
//本状态当且仅当是终点,用于封口
else if(L == 1 && R == 2 && i == s && j == t) return val;
}
std::swap(now, nxt);
}
f[nxt].clear();
//末尾的竖分割线到了下一行就变成了行首的分割线,把状态《《给分割线腾出地方
for(auto &k:f[now]) f[nxt][(k.first << 2) & U] += k.second;
std::swap(now, nxt);
}
return 0;
}
int main() {
init();
printf("%lld\n", work());
return 0;
}
P5056 【模板】插头dp的更多相关文章
- 模板—插头dp(Ural 1519 Formula 1)
括号表示法: 据说比下一个要快而且灵活. #include<iostream> #include<cstring> #include<cstdio> #define ...
- 插头DP模板
/* 插头dp模板 抄的GNAQ 的 括号表示法 */ #include<cstdio> #include<algorithm> #include<cstring> ...
- 模板:插头dp
前言: 严格来讲有关dp的都不应该叫做模板,因为dp太活了,但是一是为了整理插头dp的知识,二是插头dp有良好的套路性,所以姑且还叫做模板吧. 这里先推荐一波CDQ的论文和这篇博客http://www ...
- bzoj1814 Ural 1519 Formula 1(插头dp模板题)
1814: Ural 1519 Formula 1 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 924 Solved: 351[Submit][Sta ...
- LG5056 【模板】插头dp
题意 题目背景 ural 1519 陈丹琦<基于连通性状态压缩的动态规划问题>中的例题 题目描述 给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路.问有多少种铺法? 输 ...
- 【模板】插头dp
题目描述 题解: 插头$dp$中经典的回路问题. 首先了解一下插头. 一个格子,上下左右四条边对应四个插头.就像这样: 四个插头. 一个完整的哈密顿回路,经过的格子一定用且仅用了两个插头. 所以所有被 ...
- [学习笔记]插头dp
基于连通性的状压dp 巧妙之处:插头已经可以表示内部所有状态了. 就是讨论麻烦一些. 简介 转移方法:逐格转移,分类讨论 记录状态方法:最小表示法(每次要重新编号,对于一类没用“回路路径”之类的题,可 ...
- 插头dp小结
插头dp: \(A:\)插头dp是什么? \(B:\)一种基于连通性状态压缩的动态规划问题 \(A:\)请问有什么应用呢? \(B:\)各种网格覆盖问题,范围允许状压解决,常用于计算方案数与联通块权值 ...
- 插头dp
插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...
随机推荐
- [转]在 Windows 操作系统中的已知安全标识符(Sid security identifiers)
安全标识符 (SID) 是用于标识安全主体或安全组在 Windows 操作系统中的可变长度的唯一值.常用 Sid 的 Sid 标识普通用户的一组或通用组.跨所有操作系统,它们的值保持不变. 此信息可用 ...
- Visual Studio 小工具
折叠解决方案的每个项(Collapse Solution) 功能:折叠解决方案视图窗口中的解决方案或项目级别的每个项.包括嵌套在解决方案文件夹中的子项,引用和属性文件夹扩展节点. 源代码的文件头实现方 ...
- svn 撤销修改
1,更新到最新版本 不知道是哪个文件的问题时,可以svn log查看日志,基本上可以通过哪一次提交修改了哪一个文件推算出 是哪个文件的问题. 若知道是哪个文件的问题,直接svn log 文件名 大致确 ...
- 类型:.net;问题:iis注册;结果:.net4.0注册到IIS ,重新注册IIS ,iis注册
.net4.0注册到IIS ,重新注册IIS ,iis注册 IIS和.netfw4.0安装顺序是从前到后,如果不小心颠倒了,无所谓. 打开程序-运行-cmd:输入一下命令重新注册IIS C:\WI ...
- openGL 预定义变量04
OpenGL4.0 GLSL预定义变量 GLSL为不同的渲染阶段定义了一些特定的变量.这些预定义(也叫做内置变量)有特定的属性. 所有的预定义变量都以gl_开头.用户定义的变量不能以此开头. 下面分类 ...
- 【MySQL】20个经典面试题(转)
原文链接:http://bbs.51cto.com/thread-1470880-1.html Part2:经典题目 1.MySQL的复制原理以及流程 基本原理流程,3个线程以及之间的关联: 2.my ...
- 【276】◀▶ Python 字符串函数说明
参考:Python 字符串函数 01 capitalize 把字符串的第一个字符大写,其他字母变小写. 02 center 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串. ...
- C语言基础问题总结
Double 类型用 %f 接受会产生错误,应该用%lf C语言中SIN,COS的参数为弧度,角度应先转换为弧度才能计算,否则出错 三角形的判断条件,任意两边长度和大于第三边 闰年判断条件整百年为40 ...
- maven安装第三方jar包到本地仓库
添加项目依赖的时候,有些jar下载不下来,只有手动下载或安装到本地仓库了 首先下载所需要的jar,放到指定的文件夹 然后执行如下命令: mvn install:install-file -Dfile= ...
- Nginx 正向代理和反向代理
正向代理的概念 正向代理,也就是传说中的代理,他的工作原理就像一个跳板,简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器这个代理服务器呢,他能访问那个我不能访问的网站于是我先连上代 ...