题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法?

思路:

  本来是很基础的题,顿时不知道进入了哪个坑。这篇插头DP的文章够详细,推荐一看(最好不要照抄代码)。

  细节要小心,比如输出用I64d,必须用long long,判断是否无哈密顿回路,位操作等等。

  这次仍然用括号表示法,1表示(,2表示)。

 #include <bits/stdc++.h>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=;
const int mod=;
const int NN=;
char g[N][N];
int cur, n, m, ex, ey;
struct Hash_Map
{
int head[mod]; //桶指针
int next[NN]; //记录链的信息
int status[NN]; //状态
LL value[NN]; //状态对应的DP值。
int size; void clear() //清除哈希表中的状态
{
memset(head, -, sizeof(head));
size = ;
} void insert(int st, LL val) //插入状态st的值为val
{
int h = st%mod;
for(int i=head[h]; i!=-; i=next[i])
if(status[i] == st) //这个状态已经存在,累加进去。
{
value[i] += val;
return ;
}
status[size]= st; //找不到状态st,则插入st。
value[size] = val;
next[size] = head[h] ; //新插入的元素在队头
head[h] = size++;
}
}hashmap[]; int getbit(int s,int pos) //取出状态s的第pos个插头
{
int bit=;
if(s&(<<(*pos+))) bit+=; //高位对应高位
if(s&(<<*pos)) bit+=;
return bit;
}
int setbit(int s,int pos,int bit) //将状态s的第pos个插头设置为bit
{
if(s&(<<*pos )) s^=<<(*pos);
if(s&(<<(*pos+))) s^=<<(*pos+);
return (s|(bit<<*pos));
} int Fr(int s,int pos,int bit) //寻找状态s的第pos个插头对应的右括号。
{
int cnt=;
for(pos+=; pos<m; pos++)
{
if(getbit(s, pos)==-bit) cnt++;
if(getbit(s, pos)==bit) cnt--;
if(cnt==-) return setbit(s, pos, -bit);
}
}
int Fl(int s,int pos,int bit) //寻找状态s的第pos个插头对应的左括号。
{
int cnt=;
for(pos--; pos>=; pos--)
{
if(getbit(s, pos)==-bit) cnt++;
if(getbit(s, pos)==bit) cnt--;
if( cnt==-) return setbit(s, pos, -bit);
}
} void DP(int i,int j) //非障碍空格
{
for(int k=,t; k<hashmap[cur^].size; k++)
{
int s=hashmap[cur^].status[k];
LL v=hashmap[cur^].value[k];
int R=getbit(s,j), D=getbit(s,j+);
if(g[i][j]=='*') //障碍格子
{
if( R== && D== ) hashmap[cur].insert(s, v);
continue ;
}
if(R && D) //两个括号
{
t=(setbit(s,j,)&setbit(s,j+,));
if(R==D) //同个方向的括号
{
if(R==) t=Fr(t, j, ); //要改
else t=Fl(t, j, );
hashmap[cur].insert(t, v);
}
if( R== && D== ) //不同的连通分量
hashmap[cur].insert(t, v);
if(i==ex && j==ey && R== && D== ) //终点时'('和')'才可以合并。
hashmap[cur].insert(t, v);
}
else if(R || D) //仅1个括号
{
hashmap[cur].insert(s,v);
if(R) t=setbit(setbit(s,j,),j+,R);
else t=setbit(setbit(s,j+,),j,D);
hashmap[cur].insert(t,v);
}
else //无括号
hashmap[cur].insert( setbit(s,j,)|setbit(s,j+,), v);
}
} void cal()
{
if(ex==-) return ; //无空格
for(int i=; i<n; i++)
{
cur^=;
hashmap[cur].clear();
for(int j=; j<hashmap[cur^].size; j++) //新行,需要左移一下状态。
if( getbit( hashmap[cur^].status[j], m)== ) //多余的状态需要去除
hashmap[cur].insert( hashmap[cur^].status[j]<<, hashmap[cur^].value[j] );
for(int j=; j<m; j++)
{
cur^=;
hashmap[cur].clear();
DP(i,j);
if(i==ex && j==ey) return ; //终点
}
}
} LL print()
{
for(int i=; i<hashmap[cur].size; i++) //寻找轮廓线状态为0的值。
if( hashmap[cur].status[i]== )
return hashmap[cur].value[i];
return ;
}
int main()
{
//freopen("input.txt", "r", stdin);
while(~scanf("%d%d",&n,&m))
{
ex=ey=-;
cur=;
for(int i=; i<n; i++) //输入矩阵
for(int j=; j<m; j++)
{
char c=getchar();
if(c=='.'||c=='*')
{
g[i][j]=c;
if( c=='.' ) ex=i,ey=j;//终点空格
}
else j--;
} hashmap[cur].clear();
hashmap[cur].insert(, ); //初始状态
cal();
cout<<print()<<endl;
}
return ;
}

AC代码

URAL 1519 Formula 1 (插头DP,常规)的更多相关文章

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

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

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

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

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

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

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

  5. Ural 1519 Formula 1 插头DP

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

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

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

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

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

  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. Several ports (8005, 8080, 8009) required

    Several ports (8005, 8080, 8009) required by Tomcat v7.0 Server at localhost are already in use. The ...

  2. UVa 12661 Funny Car Racing (dijkstra)

    题意:给定一个有向图,每条路有5个整数修饰,u, v, a, b, t,表示起点为u,终点为v,打开时间a,关闭时间为b,通过时间为t,打开关闭是交替进行的, 问你从s到t最短时间是多少. 析:使用d ...

  3. AWS AutoScaling的一个ScaleDown策略问题以及解决方法

    此文已由作者袁欢授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1. AWS AutoScaling简介 AutoScaling是AWS的一个重要服务,用来弹性的自动创建(S ...

  4. Codeforces764C【DFS】

    前言,根据最终图的样貌搞真厉害 "缩点判根度为结点数-1"牛逼 ----- 题意: 找一个根使得不带根的所有子树内部颜色都相同: 思路: 如果存在两个颜色不一样的连在一起,根就是他 ...

  5. E. Similarity of Subtrees【hash】

    题意: 给你一棵树,问你有多少个组合的相似: 相似是a结点的子树和b结点的子树的每一层的结点数相等: 思路: HASH来搞: 主要也没学过散列表,以及一个散列函数的构造: 其实看下面程序很简单,手跑案 ...

  6. CodeForces660B【模拟—水】

    感觉模拟题用函数分块写比较清晰~传参的话,字符串要么直接全局,或者指针也是容易操作,总之思路清晰,然后分块清晰,模拟wa的少吧. 这题水题,不说了. #include <bits/stdc++. ...

  7. HDOJ2579,BFS(三维数组标记)

    三维数组对于我这个萌萌的新手来说真是酷酷的,帅到不行,,, 三维数组前面还看到空间的哪一题HDOJ1240,这一题时间上的标记,更酷了!!! 不说废话了,贴一发代码: #include <std ...

  8. Unity2d 骨骼动画1:介绍

    http://bbs.9ria.com/thread-401613-1-1.html by Orlando Pereira and PedroPereira3 days ago2 Comments 在 ...

  9. 51nod1076(tarjan)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1076 题意:中文题诶- 思路:先用tarjan找出所有桥,再用 ...

  10. 初识DetNet:确定性网络的前世今生

    在刚刚落幕的2019中国 SDN/NFV/AI大会上,确定性网络(Deterministic Networking)成为了大家讨论的热点话题之一.随着工业物联网(IIoT)的兴起和工业4.0的提出,T ...