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 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...
随机推荐
- mysql 安装与配置、使用
http://www.cnblogs.com/shenliang123/p/3203546.html CentOs中mysql的安装与配置 在linux中安装数据库首选MySQL,Mysql数据库的第 ...
- Loadrunner IP欺骗
一.为什么要设置IP欺骗 1. 当某个IP的訪问过于频繁,或者訪问量过大时,server会拒绝訪问请求.这时候通过IP欺骗能够添加訪问频率和訪问量,以达到压力測试的效果. 2. 某些server配置了 ...
- 【转载】Http协议与TCP协议简单理解
在C#编写代码,很多时候会遇到Http协议或者TCP协议,这里做一个简单的理解.TCP协议对应于传输层,而HTTP协议对应于应用层,从本质上来说,二者没有可比性.Http协议是建立在TCP协议基础之上 ...
- C# -- 推断字符能否转化为整形
int iNum = 0; string sNumber = "1003"; int iResult = 0; int.TryParse(sNumber, out iResult) ...
- Intel Naming Strategy--1
http://en.wikipedia.org/wiki/Mobile_Internet_device Computer sizes Classes of computers Larger S ...
- Go语言测试代码
第一次学go语言,测试代码 package main import "fmt" var age int; const sex = 0 func init() { fmt.Print ...
- HDOJ1002
#include <iostream>#include<stdio.h> using namespace std;int main(){ int T, count_T; cha ...
- Linux下编译安装源码包软件 configure ,make, make install, make test/check, make clean
http://www.360doc7.net/wxarticlenew/541275971.html 一.什么是源码包软件? 顾名思义,源码包就是源代码的可见的软件包,基于Linux和BSD系统的软件 ...
- 轮廓线DP:poj 2279 Mr. Young's Picture Permutations
poj 2279 Mr. Young's Picture Permutations \(solution:\) 首先摘取一些关键词:(每行不超过它后面的行)(每排学生安排高度从左到右减少)(学生的高度 ...
- js获取三天后的日期
js获取三天后的日期 setDate getNowAddTreeFormatDate() { var date = new Date(); date.setDate(date.getDate()+3) ...