正题

题目链接:https://www.luogu.com.cn/problem/P5056


题目大意

\(n*m\)的网格,求有多少条回路可以铺满整个棋盘。


解题思路

插头\(dp\)的,写法是按照题解上的写法。

状态用的是括号匹配,然后用了哈希+邻接表(挂表)还有滚动数组优化空间

然后可以看题解学


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int P=133331;
struct node{
int to,next;
}a[P*2];
int n,m,o,tot,zx,zy,t[2],bit[25],ls[P],S[2][P],v[25][25];
long long ans,dp[2][P];
char st[25];
void Add(int s,long long v){
int x=s%P;
for(int i=ls[x];i;i=a[i].next)
if(S[o][a[i].to]==s)
{dp[o][a[i].to]+=v;return;}
t[o]++;dp[o][t[o]]=v;S[o][t[o]]=s;
a[++tot].to=t[o];a[tot].next=ls[x];ls[x]=tot;
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",st+1);
for(int j=1;j<=m;j++)
if(st[j]=='.'){v[i][j]=1;zx=i;zy=j;}
}
for(int i=0;i<=12;i++)bit[i]=(1<<(i<<1));
t[o]=1;S[o][1]=0;dp[o][1]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=t[o];j++)S[o][j]<<=2;//将右插头移到最左边
for(int j=1;j<=m;j++){
o^=1;tot=t[o]=0;
memset(ls,0,sizeof(ls));
int s,dpl,rpl;long long w;
for(int k=1;k<=t[!o];k++){
s=S[!o][k];w=dp[!o][k];
dpl=(s>>(j<<1))%4;
rpl=(s>>(j-1<<1))%4;
if(!v[i][j]){//障碍
if(!dpl && !rpl)Add(s,w);//不能有插头
}
else if(!dpl && !rpl){//两边都没有插头
if(v[i+1][j]&&v[i][j+1])//开一个左上角插头
Add(s+2*bit[j]+bit[j-1],w);
}
else if(!dpl && rpl){//只有右插头
if(v[i+1][j])Add(s,w);
if(v[i][j+1])Add(s-rpl*bit[j-1]+rpl*bit[j],w);
}
else if(dpl && !rpl){//只有下插头
if(v[i+1][j])Add(s-dpl*bit[j]+dpl*bit[j-1],w);
if(v[i][j+1])Add(s,w);
}
else if(dpl==1&&rpl==1){
int c=1;
for(int p=j+1;p<=m;p++){
if((s>>(p<<1))%4==1)c++;
if((s>>(p<<1))%4==2)c--;
if(!c){Add(s-bit[j]-bit[j-1]-bit[p],w);break;}
} }
else if(dpl==2&&rpl==2){
int c=1;
for(int p=j-2;p>=0;p--){
if((s>>(p<<1))%4==2)c++;
if((s>>(p<<1))%4==1)c--;
if(!c){Add(s-2*bit[j]-2*bit[j-1]+bit[p],w);break;}
}
}
else if(dpl==1&&rpl==2)
Add(s-2*bit[j-1]-bit[j],w);
else if(dpl==2&&rpl==1)
if(i==zx&&j==zy)ans+=w;
}
}
}
printf("%lld\n",ans);
return 0;
}

P5056-[模板]插头dp的更多相关文章

  1. 模板—插头dp(Ural 1519 Formula 1)

    括号表示法: 据说比下一个要快而且灵活. #include<iostream> #include<cstring> #include<cstdio> #define ...

  2. P5056 【模板】插头dp

    \(\color{#0066ff}{ 题目描述 }\) 给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路.问有多少种铺法? \(\color{#0066ff}{输入格式}\) 第1 ...

  3. 插头DP模板

    /* 插头dp模板 抄的GNAQ 的 括号表示法 */ #include<cstdio> #include<algorithm> #include<cstring> ...

  4. 模板:插头dp

    前言: 严格来讲有关dp的都不应该叫做模板,因为dp太活了,但是一是为了整理插头dp的知识,二是插头dp有良好的套路性,所以姑且还叫做模板吧. 这里先推荐一波CDQ的论文和这篇博客http://www ...

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

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

  6. LG5056 【模板】插头dp

    题意 题目背景 ural 1519 陈丹琦<基于连通性状态压缩的动态规划问题>中的例题 题目描述 给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路.问有多少种铺法? 输 ...

  7. 【模板】插头dp

    题目描述 题解: 插头$dp$中经典的回路问题. 首先了解一下插头. 一个格子,上下左右四条边对应四个插头.就像这样: 四个插头. 一个完整的哈密顿回路,经过的格子一定用且仅用了两个插头. 所以所有被 ...

  8. [学习笔记]插头dp

    基于连通性的状压dp 巧妙之处:插头已经可以表示内部所有状态了. 就是讨论麻烦一些. 简介 转移方法:逐格转移,分类讨论 记录状态方法:最小表示法(每次要重新编号,对于一类没用“回路路径”之类的题,可 ...

  9. 插头dp小结

    插头dp: \(A:\)插头dp是什么? \(B:\)一种基于连通性状态压缩的动态规划问题 \(A:\)请问有什么应用呢? \(B:\)各种网格覆盖问题,范围允许状压解决,常用于计算方案数与联通块权值 ...

  10. 插头dp

    插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...

随机推荐

  1. C#录音从声卡

    原文   http://stackoverflow.com/questions/18812224/c-sharp-recording-audio-from-soundcard 我想从我的声卡(输出)录 ...

  2. C++面试题(四)——智能指针的原理和实现

    C++面试题(一).(二)和(三)都搞定的话,恭喜你来到这里,这基本就是c++面试题的最后一波了.     1,你知道智能指针吗?智能指针的原理.     2,常用的智能指针.     3,智能指针的 ...

  3. Mysql---C#在cmd中使用mysqldump导出sql文件

    一.概述 本文描述了在C#中利用mysqldump工具导出sql文件. 二.代码片段 CmdHelper类代码如下: public class CmdHelper { public static st ...

  4. WPF---数据绑定(二)

    一.绑定到非UI元素 上篇中,我们绑定的数据源均是派生自UIElement的WPF元素.本篇描述的绑定数据源是一个我们自定义的普通的类型. 注:尽管绑定的数据源可以是任意类型的对象,但Path必须总是 ...

  5. js对url进行编码和解码

    编码 只有 0-9[a-Z] $ - _ . + ! * ' ( ) , 以及某些保留字,才能不经过编码直接用于 URL. 例如:搜索的中文关键字,复制网址之后再粘贴就会发现该URL已经被转码. 1. ...

  6. 通用Mapper学习

    <通用Mapper>部分注解    @Table(name="tableName")用法: 这个注解写在实体类的上面 指定数据库表的名字作用: 建立实体类和数据库表之间 ...

  7. Inject-APC(Ring0)

    1 #include "stdafx.h" 2 #include <iostream> 3 #include <Windows.h> 4 #include ...

  8. 目录-理解ASP.NET Core

    <理解ASP.NET Core>基于.NET5进行整理,旨在帮助大家能够对ASP.NET Core框架有一个清晰的认识. 目录 [01] Startup [02] Middleware [ ...

  9. eval()函数的使用

    1.eval() 函数作用:可以接受一个字符串str作为参数,并把这个参数作为脚本代码来 执行. 2.参数情况:(1)如果参数是一个表达式,eval() 函数将执行表达式: (2) 如果参数是Java ...

  10. Ecplise项目导入IDEA(纯小白名词解释)

    1. Module 模块 一个大的项目不仅仅是只有Java的源文件,还有数据库,服务器,web等等文件一起使用,将类似于这样分类的文件定义为 module 例如 core Module(核心).web ...