插头dp

洛谷 黑题板子?

P5056

给出n×m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路。问有多少种铺法?

1、轮廓线

简单地说,轮廓线就是已决策格子和未决策格子的分界线;

2,插头dp以每一个格子进行一次转移;

3,一般设 dp[i][j][state]为(i,j)位置,状态为state的方案数(或者代价,等等让你求的东西……)

所以我们状压什么呢?轮廓线。

DP求解棋盘问题是逐格转移的。所以已经转移过的格子和没转移过的格子被一个折线分成了两半儿。这个折线就是轮廓线。

注意轮廓线状态来确定用几进制数表示,例如这道题有三种状态可以用三进制表示,但是太麻烦 蒟蒻不会 ;

可以用四进制,因为我们一般用的都是二进制的运算,我们可以用两个二进制数表示一个四进制数;

可以用哈希表存储状态,

4,一般的,对于dp数组,我们可以滚动

一些细节代码里看,由于我还没写,先用学长的;

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define int ll
#define maxn 100010
#define mod 1926223
using namespace std;
inline int read()
{
int x = 0 , f = 1 ; char ch = getchar() ;
while(!isdigit(ch)) { if(ch == '-') f = -1 ; ch = getchar() ; }
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0' , ch = getchar() ;
return x * f ;
}
int n , m , hash[mod + 1] , dp[2][mod + 1] , vis[2][mod + 1] , cnt[2] ;
int now , mp[22][22] , endx , endy , ans ;
char opt[22] ;
inline void insert(int x , int k)
{
int tmp = x % mod ;
while(hash[tmp])
{
if(vis[now][hash[tmp]] == x) {
dp[now][hash[tmp]] += k ; return ;
}
tmp = (tmp + 1) % mod ;
// cout << "!" << endl ;
}
hash[tmp] = ++cnt[now] ; vis[now][cnt[now]] = x ; dp[now][cnt[now]] = k ;
}
inline void work()
{
dp[0][1] = 1 ; cnt[0] = 1 ; vis[0][1] = 0 ;
for(int i = 1 ; i <= n ; ++i)
{
for(int j = 1 ; j <= m ; ++j)
{
cnt[now ^= 1] = 0 ;
memset(hash , 0 , sizeof hash) ;
for(int k = 1 ; k <= cnt[now ^ 1] ; ++k)
{
int S = vis[now ^ 1][k] , L = (S >> ((j - 1) * 2)) & 3 , R = (S >> (j << 1)) & 3 ;//注意这个就是取出捆绑的两个二进制数;
int val = dp[now ^ 1][k] ;
if(!mp[i][j]) {
// if(!L && !R)
insert(S , val) ;
continue ;
}
if(!L && !R)
{
if(mp[i+1][j] && mp[i][j+1]) insert(S ^ (1 << ((j - 1) << 1)) ^ (2 << (j << 1)) , val) ;
}
if(!L && R)
{
if(mp[i][j+1]) insert(S , val) ;
if(mp[i+1][j]) insert(S ^ (R << (j << 1)) ^ (R << ((j - 1) << 1)) , val) ;
}
if(L && !R)
{
if(mp[i+1][j]) insert(S , val) ;
if(mp[i][j+1]) insert(S ^ (L << ((j - 1) << 1)) ^ (L << (j << 1)) , val) ;
}
if(L == 1 && R == 1)
{
int du = 0 ;
for(int p = j + 1 ; ; ++p)
{
int state = (S >> ((p - 1) << 1)) & 3 ;
if(state == 1) du ++ ;
if(state == 2) du -- ;
if(du == 0) {
int dou = S ^ (1 << ((j - 1) << 1)) ^ (1 << (j << 1)) ;
insert(dou ^ (2 << ((p - 1) << 1)) ^ (1 << ((p - 1) << 1)) , val) ;
break ;
}
}
}
if(L == 2 && R == 2)
{#nvluf ec j
int du = 0 ;
for(int p = j ; ; --p)
{
int state = (S >> ((p - 1) << 1)) & 3 ;
if(state == 1) du ++ ;
if(state == 2) du -- ;
if(du == 0) {
int dou = S ^ (2 << ((j - 1) << 1)) ^ (2 << (j << 1)) ;
insert(dou ^ (1 << ((p - 1) << 1)) ^ (2 << ((p - 1) << 1)) , val) ;
break ;
}
}
}
if(L == 2 && R == 1)
insert(S ^ (2 << ((j - 1) << 1)) ^ (1 << (j << 1)) , val);
if(L == 1 && R == 2 && i == endx && j == endy)
ans += val ;
}
}
for(int j = 1 ; j <= cnt[now] ; ++j) vis[now][j] <<= 2 ;
}
printf("%lld\n" , ans) ;
}
signed main()
{
n = read() , m = read() ;
for(int i = 1 ; i <= n ; ++i) {
scanf("%s" , opt + 1) ;
for(int j = 1 ; j <= m ; ++j)
if(opt[j] == '.')
mp[i][j] = 1 , endx = i , endy = j ;
}
work() ;
}

插头 dp的更多相关文章

  1. 插头dp

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

  2. HDU 4113 Construct the Great Wall(插头dp)

    好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...

  3. HDU 4949 Light(插头dp、位运算)

    比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...

  4. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

  5. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

  6. HDU 1693 Eat the Trees(插头DP)

    题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...

  7. HDU 4064 Carcassonne(插头DP)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4064 Problem Description Carcassonne is a tile-based ...

  8. URAL 1519 基础插头DP

    题目大意: 给定一个图,一部分点'*'作为障碍物,求经过所有非障碍点的汉密尔顿回路有多少条 基础的插头DP题目,对于陈丹琦的论文来说我觉得http://blog.sina.com.cn/s/blog_ ...

  9. uva 11270 - Tiling Dominoes(插头dp)

    题目链接:uva 11270 - Tiling Dominoes 题目大意:用1∗2木块将给出的n∗m大小的矩阵填满的方法总数. 解题思路:插头dp的裸题,dp[i][s]表示第i块位置.而且该位置相 ...

  10. bzoj 1187: [HNOI2007]神奇游乐园 插头dp

    1187: [HNOI2007]神奇游乐园 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 668  Solved: 337[Submit][Statu ...

随机推荐

  1. 3D人物移动控制实现方案

    要控制3D人物在3D世界中进行正常的移动.转向,一般有两种情况: 1.使用人物动画控制人物 的移动 转向 2.使用脚本控制人物 的移动.转向 对方案一: Animator 组件勾选上 Apply Ro ...

  2. tomcat7升级到tomcat8注意事项

    第一点:context.xml配置jndi的参数修改   maxActive 替换为 :maxTotal maxWait 替换为 :maxWaitMillis factory="org.ap ...

  3. MyBatis源码骨架分析

    源码包分析 MyBatis 源码下载地址:https://github.com/MyBatis/MyBatis-3 MyBatis源码导入过程: 下载MyBatis的源码 检查maven的版本,必须是 ...

  4. Oracle用户自定义异常

    注意:普通的查询语句不会出现异常,只有使用into对变量进行赋值的时候才会发生异常 --系统变量: notfound --> if sql%notfund then 如果这个表达式为真,则 (增 ...

  5. html基础:jquery的ajax获取form表单数据

    jq是对dom进行的再次封装.是一个js库,极大简化了js使用 jquery库在js文件中,包含了所有jquery函数,引用:<script src="jquery-1.11.1.mi ...

  6. 二、loadrunner参数化连接数据库

    2.连接sqlserver数据库.oracle数据库或mysql数据库(只有mysql数据库驱动需要先手动安装) 2.1.新建一个参数,随便设置file还是table类型之类的 2.2.点击Data ...

  7. Netty之旅三:Netty服务端启动源码分析,一梭子带走!

    Netty服务端启动流程源码分析 前记 哈喽,自从上篇<Netty之旅二:口口相传的高性能Netty到底是什么?>后,迟迟两周才开启今天的Netty源码系列.源码分析的第一篇文章,下一篇我 ...

  8. 初等函数——幂函数(Power Function)

    幂函数(Power function)是形如f(x)=xa的函数,a∈R是实数.即以底数为自变量,幂为因变量,指数为常数的函数称为幂函数. 性质 幂函数的图像一定会出现在第一象限内,一定不会出现在第四 ...

  9. JVM运行时数据区--纵向补充--对象的实例化内存布局与访问定位

    对象的实例化 创建对象的方式 1.new:最常见的方式(本质是构造器) 变形1 : Xxx的静态方法 变形2 : XxBuilder/XxoxFactory的静态方法 2.Class的newInsta ...

  10. x86-TSO : 适用于x86体系架构并发编程的内存模型

    Abstract : 如今大数据,云计算,分布式系统等对算力要求高的方向如火如荼.提升计算机算力的一个低成本方法是增加CPU核心,而不是提高单个硬件工作效率. 这就要求软件开发者们能准确,熟悉地运用高 ...