bzoj 1814: Ural 1519 Formula 1【插头dp】
设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】的更多相关文章
- 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 ...
- bzoj 1814 Ural 1519 Formula 1 ——插头DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1814 普通的插头 DP .但是调了很久.注意如果合并两个 1 的话,不是 “把向右第一个 2 ...
- bzoj 1814: Ural 1519 Formula 1 插头dp经典题
用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. #include<iostream> #include<cstdio> #include<cstr ...
- bzoj1814 Ural 1519 Formula 1(插头dp模板题)
1814: Ural 1519 Formula 1 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 924 Solved: 351[Submit][Sta ...
- 【BZOJ1814】Ural 1519 Formula 1 插头DP
[BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...
- Ural 1519 Formula 1 插头DP
这是一道经典的插头DP单回路模板题. 用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制. 1.当同时存在左.上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连 ...
- BZOJ1814: Ural 1519 Formula 1(插头Dp)
Description Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic gam ...
- 【Ural】1519. Formula 1 插头DP
[题目]1519. Formula 1 [题意]给定n*m个方格图,有一些障碍格,求非障碍格的哈密顿回路数量.n,m<=12. [算法]插头DP [题解]<基于连通性状态压缩的动态规划问题 ...
- 【BZOJ1814】Ural 1519 Formula 1 (插头dp)
[BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...
随机推荐
- 【Java编程】建立一个简单的JDBC连接-Drivers, Connection, Statement and PreparedStatement
本blog提供了一个简单的通过JDBC驱动建立JDBC连接例程.并分别通过Statement和PreparedStatement实现对数据库的查询. 在下一篇blog中将重点比較Statement与P ...
- 心情日记app总结 数据存储+服务+广播+listview+布局+fragment+intent+imagebutton+tabactivity+美工
---恢复内容开始--- 结果截图如下: 第一张图是程序主界面,主要是显示记事列表的一些个事件.旁边的侧拉框是自己登陆用的.可以设置密码.可以查看反馈与关于等信息. 点击第一张图片下方的图标,会显示不 ...
- Hadoop教程(一)
英文原文:cloudera,编译:ImportNew – Royce Wong Hadoop从这里开始!和我一起学习下使用Hadoop的基本知识,下文将以Hadoop Tutorial为主体带大家走一 ...
- 在OpenStack中绕过或停用security group (iptables)
眼下.OpenStack中默认採用了security group的方式.用系统的iptables来过滤进入vm的流量.这个本意是为了安全,可是往往给调试和开发带来一些困扰. 因此,暂时性的禁用它能够排 ...
- Qt浅谈之二十一log调试日志
一.简单介绍 近期因调试code时,想了解程序的流程,但苦于没有一个简易的日志记录,不停使用qDebug打印输出,而终于提交代码时得去多次删除信息打印,有时还会出现新改动的代码分不清是哪些部分.而使用 ...
- Creo二次开发--内存清理函数
我们在处理模型文件时,总会遇到内存环境的清除问题.一个干净的Creo工作环境.是保证工作能顺利完毕的保障. ProMdlEraseNotDisplayed()函数提供了清除未显示模型的功能. 当须要循 ...
- PyOpenGL下GlutBitmapCharacter的替代
虽然pyinstaller支持pyopengl,但是调用GLUT之后,在其它电脑上面运行就会出现错误,索性按照之前C#上面的办法,把字体数据和函数用python重写 fontData.py #! /u ...
- Quartz深入浅出(二)
Hello Quartz / 本文通过一个简单的样例让大家高速了解Quartz,上手.并了解Quartz内的一些关键对象 如 Scheduler.Job.Trigger.JobExecutionCon ...
- AndroidCityPicker仿IOS选择效果
近期的一个项目由于android端与IOS端须要同步,所以在城市选择器这里做了一个相似IOS的CityPicker控件,当然由于本人水平问题显示效果比IOS上面还是有一定差距的.OK先让大家看下效果. ...
- JS简单正则得到字符串中特定的值
这里就直接看演示样例吧.演示样例的目的是为了获取 a 字符串中的 c02806015 <script language="javascript"> var a = '礼 ...