设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数

括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合

下面的蓝线是黄色格子的轮廓线,dp转移要把它转到橙色轮廓线,设已经在状压的s中取到两条边的状态记为b1,b2



然后分很多情况讨论:

(i,j)是障碍:那就只能什么都不放的转移,也就是只能从b1=0,b2=0转移到新轮廓线的b1=0,b2=0

if(!a[i][j])
{
if(!b1&&!b2)
add(x,v);
}

b1=0,b2=0:因为不能空,所以只能转移一个拐角

else if(!b1&&!b2)
{
if(a[i+1][j]&&a[i][j+1])
add(x+b[j-1]+2*b[j],v);
}

b1=0或者b2=0:根据有无障碍判断能不能转移,如果(i,j+1),(i+1,j)都没有障碍的话就有两种转移,以b1=0,b2!=0为例:

一种是接上然后拐弯,这样转移后的轮廓线括号状态不变



另一种是接上直着走,转移后的轮廓线括号状态b1b2互换



b1!=0,b2=0同理

else if(!b1&&b2)
{
if(a[i][j+1])
add(x,v);
if(a[i+1][j])
add(x-b[j]*b2+b[j-1]*b2,v);
}
else if(b1&&!b2)
{
if(a[i][j+1])
add(x-b[j-1]*b1+b[j]*b1,v);
if(a[i+1][j])
add(x,v);
}

b1=b2=1或2:这样这两条线会在(i,j)格子连起来,两队括号合成一对,以b1=b2=1为例:

else if(b1==1&&b2==1)
{
for(int t=1,l=j+1;l<=m;l++)
{
if((x>>(l*2))%4==1)
t++;
if((x>>(l*2))%4==2)
t--;
if(!t)
{
add(x-b[j]-b[j-1]-b[l],v);
break;
}
}
}
else if(b1==2&&b2==2)
{
for(int t=1,l=j-2;l>=0;l--)
{
if((x>>(l*2))%4==1)
t--;
if((x>>(l*2))%4==2)
t++;
if(!t)
{
add(x+b[l]-2*b[j]-2*b[j-1],v);
break;
}
}
}

b1=2,b2=1:和上面差不多,就是把这两个括号合并就行了

else if(b1==2&&b2==1)
add(x-2*b[j-1]-b[j],v);

b1=1,b2=2:这个只有到最后一个没障碍的点才能转移,因为这是把一条线连成一个回路的最后一步

其实不用转移,直接加进答案就行了

else if(i==tx&&j==ty)
ans+=v;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=15,mod=299989;
int n,m,la,nw,a[N][N],b[N],c[2],h[300005],tx,ty;
long long ans;
char s[N];
struct qwe
{
int ne,to[2];
long long va[2];
}e[300005];
void add(int x,long long v)
{
int u=x%mod+1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].to[nw]==x)
{
e[i].va[nw]+=v;
return;
}
e[++c[nw]].ne=h[u];
e[c[nw]].to[nw]=x;
e[c[nw]].va[nw]=v;
h[u]=c[nw];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=m;j++)
if(s[j]=='.')
a[i][j]=1,tx=i,ty=j;
}
b[0]=1;
for(int i=1;i<=12;i++)
b[i]=b[i-1]<<2;
c[0]=1,e[1].va[0]=1,e[1].to[0]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=c[nw];j++)
e[j].to[nw]<<=2;
for(int j=1;j<=m;j++)
{
la=nw,nw^=1;
memset(h,0,sizeof(h));
c[nw]=0;
for(int k=1;k<=c[la];k++)
{
int x=e[k].to[la],b1=(x>>(j*2-2))%4,b2=(x>>(j*2))%4;
long long v=e[k].va[la];
if(!a[i][j])
{
if(!b1&&!b2)
add(x,v);
}
else if(!b1&&!b2)
{
if(a[i+1][j]&&a[i][j+1])
add(x+b[j-1]+2*b[j],v);
}
else if(!b1&&b2)
{
if(a[i][j+1])
add(x,v);
if(a[i+1][j])
add(x-b[j]*b2+b[j-1]*b2,v);
}
else if(b1&&!b2)
{
if(a[i][j+1])
add(x-b[j-1]*b1+b[j]*b1,v);
if(a[i+1][j])
add(x,v);
}
else if(b1==1&&b2==1)
{
for(int t=1,l=j+1;l<=m;l++)
{
if((x>>(l*2))%4==1)
t++;
if((x>>(l*2))%4==2)
t--;
if(!t)
{
add(x-b[j]-b[j-1]-b[l],v);
break;
}
}
}
else if(b1==2&&b2==2)
{
for(int t=1,l=j-2;l>=0;l--)
{
if((x>>(l*2))%4==1)
t--;
if((x>>(l*2))%4==2)
t++;
if(!t)
{
add(x+b[l]-2*b[j]-2*b[j-1],v);
break;
}
}
}
else if(b1==2&&b2==1)
add(x-2*b[j-1]-b[j],v);
else if(i==tx&&j==ty)
ans+=v;
}
}
}
printf("%lld\n",ans);
return 0;
}

bzoj 1814: Ural 1519 Formula 1【插头dp】的更多相关文章

  1. 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 ...

  2. bzoj 1814 Ural 1519 Formula 1 ——插头DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1814 普通的插头 DP .但是调了很久.注意如果合并两个 1 的话,不是 “把向右第一个 2 ...

  3. bzoj 1814: Ural 1519 Formula 1 插头dp经典题

    用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. #include<iostream> #include<cstdio> #include<cstr ...

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

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

  5. 【BZOJ1814】Ural 1519 Formula 1 插头DP

    [BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...

  6. Ural 1519 Formula 1 插头DP

    这是一道经典的插头DP单回路模板题. 用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制. 1.当同时存在左.上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连 ...

  7. BZOJ1814: Ural 1519 Formula 1(插头Dp)

    Description Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic gam ...

  8. 【Ural】1519. Formula 1 插头DP

    [题目]1519. Formula 1 [题意]给定n*m个方格图,有一些障碍格,求非障碍格的哈密顿回路数量.n,m<=12. [算法]插头DP [题解]<基于连通性状态压缩的动态规划问题 ...

  9. 【BZOJ1814】Ural 1519 Formula 1 (插头dp)

    [BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...

随机推荐

  1. libxml/HTMLparser.h file not found

    在导入asihttprequest包时出问题导入了libxml2.dylib.可是却提示libxml/HTMLparser.h file not found. 这是由于你的开发环境默认的路径无法找到这 ...

  2. LA4043 - Ants(二分图完备最佳匹配KM)

    option=com_onlinejudge&Itemid=8&page=show_problem&problem=2044">https://icpcarch ...

  3. 线程、SMP、微内核

  4. bootstrap-Table服务端分页,获取到的数据怎么再页面的表格里显示

    <table class="table table-hover" id="userTable" > <thead> <tr> ...

  5. Android版DesiredCapabilities参数配置

    前言 每一个App测试都应指定是在什么平台下,那个设备中运行那个App,而在Appium中主要是通过DesiredCapabilities来配置的. DesiredCapabilities的作用,负责 ...

  6. HBase协处理器同步二级索引到Solr(续)

    一. 已知的问题和不足二.解决思路三.代码3.1 读取config文件内容3.2 封装SolrServer的获取方式3.3 编写提交数据到Solr的代码3.4 拦截HBase的Put和Delete操作 ...

  7. 小程序多级下拉菜单demo

    小程序多级下拉菜单demo - CSDN博客 https://blog.csdn.net/github_39371177/article/details/80251211

  8. 新产品为了效果,做的比較炫,用了非常多的图片和JS,所曾经端的性能是非常大的问题,分篇记录前端性能优化的一些小经验。

    第一篇:HTTPserver 因tomcat处理静态资源的速度比較慢,所以首先想到的就是把全部静态资源(JS,CSS,image,swf) 提到单独的server,用更加高速的HTTPserver,这 ...

  9. mini_magick

    https://github.com/minimagick/minimagick class  https://www.rubydoc.info/github/minimagick/minimagic ...

  10. iframe引入页面

    将外层css框架单独存放在一个css文件之中,将iframe的css单独写在一个css文件,避免iframe中的html,body等公共部分的样式冲突. 外层框架单独写在一个css,如: frame. ...