【模板】插头dp
题解:
插头$dp$中经典的回路问题。
首先了解一下插头。
一个格子,上下左右四条边对应四个插头。就像这样:

四个插头。
一个完整的哈密顿回路,经过的格子一定用且仅用了两个插头。
所以所有被回路经过的格子有六种状态,即左上,左右,左下,上右,上下,右下。
这几个就是插头$dp$的基本。
然后我们来了解一下轮廓线。

红线就叫轮廓线。
我们可以利用轮廓线作为状态dp,将轮廓线一点点右推+下推,直到推完,这样我们就可以得出全局答案啦!!!
但是怎么转移……
插头!
我们可以稍微讨论一下,讨论拐角处的插头状态,然后转移就好了。
听起来很简单恶心。
实际上很简单恶心。
现在我们突然想到一个问题,就是状态怎么记录。
主要有两种方法,一种叫最小表示法(不是字符串的最小表示法),一种叫括号序列。
最小表示法,是将互相联通的插头归入一类。如果我们将其采用字典序最小的方法表示,那么对于某条轮廓线表示法与轮廓线状态一一对应。
括号表示法,是由于网格中两条哈密顿回路路径不可相交的性质。
如果我们认为回路有方向,比如轮廓线左面的为进,右面的为出,那我们可以将进看作‘(’,将出看作‘)’。
由于上面那条性质,我们可以知道一个括号序列对应一种轮廓线状态。
而且括号表示法比最小表示法好写。
括号表示法怎么用?
三进制。0表示'-',1表示'(',2表示')'。
压成一个数字然后用挂链存起来就好了。
(我用的括号表示法)
现在我们就差转移了。
(其实我非常不愿意在博客里写但是良心的我还是写了)
状态1:)(
直接用下面这个接上即可。

而且刚好满足括号匹配。
状态2:(-或)-
两种情况。
或
状态3:-)或-(
还是两种情况。
或
状态4:))或((
这个我们还是要放状态1的那个块。
但是不满足括号匹配怎么办?
向左/向右找一个换上。
举个例子,比如说原序列是:(()(()))()(),
然后中间两个接在一起,序列就应该成为:(()()--)()()
注意那个变号。
状态5:--
直接放插头。

状态6:()
一旦合并说明括号序列清空。
所以只能在最后一格合并状态6。
所以我们要知道最后一格在哪。
没有状态7。
上述状态都是在当前格子可填且插头指向格子可填时可选。
然后上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 15
#define ll long long
#define M 100000
int n,m;
ll bas[N];
char ch[N][N];
struct Map
{
int hed[M+],cnt[];
struct EG
{
int nxt;ll to,w;
}e[<<][];
void ae(int f,ll t,ll w,int k)
{
e[++cnt[k]][k].to = t;
e[cnt[k]][k].nxt = hed[f];
e[cnt[k]][k].w = w;
hed[f] = cnt[k];
}
void push(ll u,ll d,int k)
{
int f = (int)(u%M);
for(int j=hed[f];j;j=e[j][k].nxt)
if(e[j][k].to==u)
{
e[j][k].w+=d;
return ;
}
ae(u%M,u,d,k);
}
void clear(int k)
{
memset(hed,,sizeof(hed));
cnt[k] = ;
}
}mp;
ll ans;int tx,ty;
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",ch[i]+);
for(int j=;j<=m;j++)
if(ch[i][j]=='.')
tx=i,ty=j;
}
bas[] = ;
for(int i=;i<=m+;i++)bas[i]=bas[i-]<<;
mp.push(,,);
for(int k=,i=;i<=n;i++)
{
for(int j=;j<=mp.cnt[k];j++)mp.e[j][k].to<<=;
for(int j=;j<=m;j++)
{
k^=;mp.clear(k);
for(int o=;o<=mp.cnt[!k];o++)
{
ll now = mp.e[o][!k].to,val = mp.e[o][!k].w;
int lp = (now>>(j-)*)&,rp = (now>>j*)&;
if(ch[i][j]=='*')
{
if(!lp&&!rp)
{
mp.push(now,val,k);
}
}else
{
if(!lp&&!rp)
{
if(ch[i+][j]=='.'&&ch[i][j+]=='.')
{
ll tmp = now+bas[j-]+bas[j]*;
mp.push(tmp,val,k);
}
}else if(!lp&&rp)
{
if(ch[i+][j]=='.')
{
ll tmp = now+bas[j-]*rp-bas[j]*rp;
mp.push(tmp,val,k);
}
if(ch[i][j+]=='.')
{
ll tmp = now;
mp.push(tmp,val,k);
}
}else if(lp&&!rp)
{
if(ch[i+][j]=='.')
{
ll tmp = now;
mp.push(tmp,val,k);
}
if(ch[i][j+]=='.')
{
ll tmp = now-bas[j-]*lp+bas[j]*lp;
mp.push(tmp,val,k);
}
}else
{
if(lp==&&rp==)
{
ll tmp = now-bas[j-]-bas[j];
int sum = ;
for(int j0=j+;j0<=m+;j0++)
{
if(((now>>(j0-)*)&)==)sum++;
if(((now>>(j0-)*)&)==)sum--;
if(!sum)
{
mp.push(tmp-bas[j0-],val,k);
break;
}
}
}else if(lp==&&rp==)
{
ll tmp = now-bas[j-]*-bas[j]*;
int sum = ;
for(int j0=j-;j0>=;j0--)
{
if(((now>>(j0-)*)&)==)sum--;
if(((now>>(j0-)*)&)==)sum++;
if(!sum)
{
mp.push(tmp+bas[j0-],val,k);
break;
}
}
}else
{
if(lp==&&rp==)
{
ll tmp = now-bas[j-]*-bas[j];
mp.push(tmp,val,k);
}else if(i==tx&&j==ty)ans+=val;
}
}
}
}
}
}
printf("%lld\n",ans);
return ;
}
【模板】插头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的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路.问有多少种铺法? 输 ...
- P5056 【模板】插头dp
\(\color{#0066ff}{ 题目描述 }\) 给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路.问有多少种铺法? \(\color{#0066ff}{输入格式}\) 第1 ...
- 插头dp
插头dp 感受: 我觉得重点是理解,算法并不是直接想出怎样由一种方案变成另一种方案.而是方案本来就在那里,我们只是枚举状态统计了答案. 看看cdq的讲义什么的,一开始可能觉得状态很多,但其实灰常简单 ...
- hdu1964之插头DP求最优值
Pipes Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...
- 插头dp初探
问题描述 插头dp用于解决一类可基于图连通性递推的问题.用插头来表示轮廓线上的连通性,然后根据连通性与下一位结合讨论进行转移. 表示连通性的方法 与字符串循环最小表示不同,这种方法用于给轮廓线上的联通 ...
随机推荐
- Codeforces 1000 (A~E)
A Codehorses T-shirts 相同长度之间互相转化即可 #include<iostream> #include<cstdio> #include<cstri ...
- bzoj 2761: [JLOI2011]不重复数字【hash】
map会T,双hash会冲突--于是非酋写了个三hash #include<iostream> #include<cstdio> #include<cstring> ...
- USB转串口 FT232/PL2303芯片使用体会
现在笔记本上很少带有串口了,而串口又是做电子设计必备的通讯接口之一,好在USB转串口比较方便,市面上常用的USB转串口芯片有很多,最常见的有FT232.PL2303.CH340三种 原理:单片机的TX ...
- 微信小程序开发常见的拉起外部地图软件进行导航的功能
<view class="dh" bindtap="mapNavigation" data-addr="{{address}}"> ...
- ogg 监控脚本
section 1: #! /bin/sh PATH=/usr/local/bin:$PATHORACLE_SID=statdb ORAENV_ASK=NO. oraenv > /dev/nul ...
- Vue checkbox默认值改变
<label><input v-bind:true-value="1" v-bind:false-value="0" type=" ...
- 动手实现 Redux(一):优雅地修改共享状态
从这节起我们开始学习 Redux,一种新型的前端“架构模式”.经常和 React.js 一并提出,你要用 React.js 基本都要伴随着 Redux 和 React.js 结合的库 React-re ...
- ref 和 React.js 中的 DOM 操作
在 React.js 当中你基本不需要和 DOM 直接打交道.React.js 提供了一系列的 on*方法帮助我们进行事件监听,所以 React.js 当中不需要直接调用 addEventListen ...
- C#: static关键字的作用(转)
C#: static关键字的作用 static意思是静态,可以修饰类.字段.属性.方法 标记为static的就不用创建实例对象调用了,可以通过类名直接点出来 static三种用法: 1.用于变量前 ...
- 基于ABP的Easyui admin framework正式开放源代码
下载&反馈:http://www.webplus.org.cn v1.0 (2016/9/21) EF6+MVC5+API2+Easyui1.4.2开发 后台管理不使用iframe,全ajax ...