hash表及带注释插头dp
struct hash_map
{
node s[SZ+10];int e,adj[SZ+10];
inline void init(){e=0;memset(adj,0,sizeof(adj));}
inline void update(LL state,int val,int cnt)
{
RG int i,pos=(state%SZ+(LL)val*SZ)%SZ;
for(i=adj[pos];i&&(s[i].state!=state||s[i].val!=val);i=s[i].next);
if(!i)s[++e].state=state,s[e].val=val,s[e].cnt=cnt,s[e].next=adj[pos],adj[pos]=e;
else s[i].cnt=(s[i].cnt+cnt)%mod;
} inline void find(LL state,int val)
{
RG int i,pos=(state%SZ+(LL)val*SZ)%SZ;
for(i=adj[pos];i&&(s[i].state!=state||s[i].val!=val);i=s[i].next);
if(!i)printf("no such val\n");
else printf("cnt=%d\n",s[i].cnt);
} }f[2];
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1100000
#define mod 299989
#define P 8
#define N 100000000
ll n,m;
inline ll find(ll state,ll id){
return (state>>((id-1)<<1))&3;
}//看当前插头究竟是什么插头
//因为是四进制每两位代表一个状态
struct bignum
{
ll n[10],l;
bignum(){l=1,memset(n,0,sizeof(n));}
void clear(){while(l>1&&!n[l-1]) l--;}
void print(){
printf("%lld",n[l-1]);
for(ll i=l-2;i>=0;i--)
printf("%0*lld",P,n[i]);
printf("\n");
}
bignum operator +(bignum x)const{
bignum t=*this;
if(t.l<x.l) t.l=x.l;
t.l++;
for(ll i=0;i<t.l;i++){
t.n[i]+=x.n[i];
if(t.n[i]>=N){
t.n[i+1]+=t.n[i]/N;
t.n[i]%=N;
}
}
t.clear();
return t;
}
bignum operator =(ll x){
l=0;
while(x){
n[l++]=x%N;
x/=N;
}
return *this;
}
inline void operator +=(bignum b){*this=*this+b;}
}Ans;
struct hash_map
{
bignum val[mod];
ll key[A],hash[mod],size;
inline void init(){
memset(val,0,sizeof(val));
memset(key,-1,sizeof(key));size=0;
memset(hash,0,sizeof(hash));
}
inline void newhash(ll id,ll v){hash[id]=++size;key[size]=v;}
bignum &operator [] (const ll &state){
for(ll i=state%mod;;i=(i+1==mod)?0:i+1)
{
if(!hash[i]) newhash(i,state);
if(key[hash[i]]==state) return val[hash[i]];
}
}
}f[2];
inline void Set(ll &state,ll bit,ll val){
bit=(bit-1)<<1;
state|=3<<bit;
state^=3<<bit;
//把state高位先赋成0再把它赋成别的
state|=val<<bit;
//state表示状态
//因为插头的编号为0--m所以bit要-1
//因为是四进制,所以3<<
//全都是4进制
//2<<bit
//1<<bit
//貌似还能理解
//每两位代表一个具体状态
}
ll link(ll state,ll pos){
//找到对应的插头(用括号匹配的方式)然后
ll cnt=0,delta=(find(state,pos)==1)?1:-1;
//如果是左括号应该向右寻找右括号
//如果是右括号应该向左寻找左括号
for(ll i=pos;i&&i<=m+1;i+=delta)//一共m+1个插头
{
ll plug=find(state,i);
if(plug==1)
cnt++;//左括号数量++
else if(plug==2)
cnt--;//右括号数量++
if(cnt==0)//当左括号数量与右括号数量相等时找到匹配
return i;//找到了与当前插头对应的插头
}
return -1;
//当前状态是非法的找不到与之对应的插头
}
inline void education(ll x,ll y){
ll now=((x-1)*m+y)&1,last=now^1,tot=f[last].size;
f[now].init();
for(ll i=1;i<=tot;i++){
// printf("i=%lld\n",i);
ll state=f[last].key[i];//key状态
bignum Val=f[last].val[i];//取出上一次权值(方案数)
ll plug1=find(state,y),plug2=find(state,y+1);
//0--m编号,寻找轮廓线上编号y-1,y对应的插头
//至于为什么是y y+1,因为在上面函数里进行了减1
//编号为y-1是左右插头,y代表上下插头
if(link(state,y)==-1||link(state,y+1)==-1)
continue;
//当前括号无法找到匹配无解
if(!plug1&&!plug2){
if(x!=n&&y!=m){
//如果没有插头,直接拽过来两个插头相连(此题保证必须连通)
Set(state,y,1);
//在轮廓线上位置为y-1添加一个左括号
Set(state,y+1,2);
//y位置添加一个右括号
f[now][state]+=Val;
}
}
else if(plug1&&!plug2){
//拥有左右插头没有上下插头
//两种转移方式,转弯向下走
//这样插头状态不变
if(x!=n)
f[now][state]+=Val;
//向右连接一个插头
//向右推进要发生改变
if(y!=m){
Set(state,y,0);
Set(state,y+1,plug1);
f[now][state]+=Val;
}
}
else if(!plug1&&plug2){
//拥有上下插头而没有左右插头
//两种转移方式,向右转移
//这样插头状态不变
if(y!=m)
f[now][state]+=Val;
//向右连接一个插头
if(x!=n){
Set(state,y,plug2);
Set(state,y+1,0);
//plug2是左右插头让上下方向转弯
f[now][state]+=Val;
}
}
else if(plug1==1&&plug2==1){
//两个左括号插头相连接,然后让最靠左的右括号插头变成左括号插头
Set(state,link(state,y+1),1);
Set(state,y,0);
Set(state,y+1,0);
f[now][state]+=Val;
}
else if(plug1==1&&plug2==2){
//右插头是左括号插头,上插头是右括号插头,连在一起
//构成回路
if(x==n&&y==m)
Ans+=Val;
}
else if(plug1==2&&plug2==1){
//无脑合并
Set(state,y,0);
Set(state,y+1,0);
f[now][state]+=Val;
}
else if(plug1==2&&plug2==2){
//当你有左右插头右括号插头,上下插头为右插头
//合并为1,将最靠右左插头变为右插头
Set(state,link(state,y),2);
Set(state,y,0);
Set(state,y+1,0);
f[now][state]+=Val;
}
}
}
int main(){
scanf("%lld%lld",&n,&m);
if(n==1||m==1){printf("1\n");return 0;}
if(m>n) swap(n,m);
f[0].init();f[0][0]=1;
for(ll i=1;i<=n;i++)
{
for(ll j=1;j<=m;j++)
education(i,j);
if(i!=n){
ll now=(i*m)&1,tot=f[now].size;
for(ll j=1;j<=tot;j++)
f[now].key[j]<<=2;
}
}
Ans+=Ans;
Ans.print();
}
hash表及带注释插头dp的更多相关文章
- BZOJ.1210.[HNOI2004]邮递员(插头DP Hash 高精)
BZOJ 洛谷 http://www.cnblogs.com/LadyLex/p/7326874.html 插头DP.\(m+1\)个插头的状态需要用三进制表示:\(0\)表示无插头,\(1\)表示是 ...
- SQLServer之数据库表转化为实体类【带注释】
1.在开发过程中,有时候需要将数据库表转化为实体类.手敲除了不方便,还容易出错.本着DRY+懒人原则,参考了一位老司机的博客[见底部],并在其基础上进行了优化.[原先是不带注释的] DECLARE @ ...
- 四种方式带你层层递进解剖算法---hash表不一定适合寻找重复数据
一.题目描述 找出数组中重复的数字 > 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次. ...
- 插头dp小结
插头dp: \(A:\)插头dp是什么? \(B:\)一种基于连通性状态压缩的动态规划问题 \(A:\)请问有什么应用呢? \(B:\)各种网格覆盖问题,范围允许状压解决,常用于计算方案数与联通块权值 ...
- 【Learning】插头DP
简介 插头DP(轮廓线DP)是用来解决网格图回路问题的一种算法. 插头DP解决的经典问题就是统计经过所有格子的哈密顿回路条数,某些格子有障碍. 如果问题稍微进阶一点的话,不一定要求路径是回路.路径 ...
- HDU 4113 Construct the Great Wall(插头dp)
好久没做插头dp的样子,一开始以为这题是插头,状压,插头,状压,插头,状压,插头,状压,无限对又错. 昨天看到的这题. 百度之后发现没有人发题解,hust也没,hdu也没discuss...在acm- ...
- HDU 4949 Light(插头dp、位运算)
比赛的时候没看题,赛后看题觉得比赛看到应该可以敲的,敲了之后发现还真就会卡题.. 因为写完之后,无限TLE... 直到后来用位运算代替了我插头dp常用的decode.encode.shift三个函数以 ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
随机推荐
- Asp.NetCore 自定义中间件
这节演示一下自定义中间件,第一节我们讲到,中间件的处理流程就像一个俄罗斯套娃,那这种俄罗斯套娃型的流程内部是如何实现的呢,下面请看代码. 第一种写法是直接写在Configure方法中的,使用app ...
- JavaWeb——反射、注解
单元测试.反射.注解 1. Junit单元测试 2. 反射 3. 注解 Junit单元测试: * 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要 ...
- 从几道题目带你深入理解Event Loop_宏队列_微队列
目录 深入探究JavaScript的Event Loop Event Loop的结构 回调队列(callbacks queue)的分类 Event Loop的执行顺序 通过题目来深入 深入探究Java ...
- 最优运输(Optimal Transfort):从理论到填补的应用
目录 引言 1 背景 2 什么是最优运输? 3 基本概念 3.1 离散测度 (Discrete measures) 3.2 蒙日(Monge)问题 3.3 Kantorovich Relaxation ...
- [Python] execl读写
相关库 读:xlrd 写:xlwt 案例 要求: 将图1中的数据导以图2的形式写入另一个文件中 第一列索引关系:{1:K1-B1,2:K1-B2} ...(18列) 思路: 按行读取数据,根据索引关系 ...
- 删除所有空白列 cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log1 sed ‘s/[ \t]*$//g' 删除所有空格 sed -i s/[[:space:]]//g yum.log
2.删除行末空格 代码如下: 删除所有空白列 cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log1 sed 's/[ \t]* ...
- https://www.jqhtml.com/30047.html strace + 命令: 这条命令十分强大,可以定位你程序到底是哪个地方出了问题
https://www.jqhtml.com/30047.html 我的Linux手册 服务器 浏览数:72 2019-1-30 原文链接 基础安装 # CentOS sudo yum install ...
- Docker——Registry搭建私有镜像仓库
前言 在 Docker 中,当我们执行 docker pull xxx 的时候,它实际上是从 registry.hub.docker.com 这个地址去查找,这就是Docker公司为我们提供的公共仓库 ...
- du -cs /var/lib/BackupPC/pc/10.1.60.211/目录名
# du -cs /var/lib/BackupPC/pc/10.1.60.211/7870236 /var/lib/BackupPC/pc/10.1.60.211/7870236 总用量
- Linux内存带宽的一些测试笔记
Linux内存带宽的一些测试笔记 首页 所有文章 2014年10月 GNU/Linux系统 2014-10-21 13:20 GNU/LINUX系统 内存带宽 1k 字 669 次 最近要测一下 ...