【Ural】1519. Formula 1 插头DP
【题目】1519. Formula 1
【题意】给定n*m个方格图,有一些障碍格,求非障碍格的哈密顿回路数量。n,m<=12。
【算法】插头DP
【题解】《基于连通性状态压缩的动态规划问题》 by CDQ(万恶之源T_T)
如果你想学最小表示法,当然首推kuangbinの博客。
基本思想是逐格推进,维护轮廓线的m+1个插头的状态,每个插头有一个编号,连通的插头编号相同。
由于只转移和记录有效状态,所以时空复杂度都大大优于普通的状压DP。
1.存储:容易发现连通编号至多0~6,所以用数字每三个二进制位存一个插头编号,用hash表存数字,同状态须合并来保证状态总数。
解码:强制从左到右是从高到低,倒着&7就能解码出数组了。
2.最小表示法:过程中会出现合并编号和新建编号的操作,通过暴力最小化的方法使得编号位0~6,称为最小表示法。
编码:最小化的过程体现在编码,用桶vis记老编号对应的新编号,扫一遍即可。新建的编号设为6。
3.转移:本题的障碍格可以直接不转移,因为插头也不会变化,下面讨论非障碍格的转移(依赖于左插头和上插头)。
Ⅰ存在左插头和上插头
如果同编号,那么只有最后一个非障碍格才能闭合,否则状态无效。
如果不同编号,可以连接,遍历所有插头将和左插头连通的编号改成上插头。
Ⅱ存在左插头或上插头
如果右能加插头就转移,如果下能加插头就转移。
Ⅲ不存在左插头和上插头
如果右和下都能加插头就转移,插头编号6。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=,MOD=,S=;
int c[maxn],map[maxn][maxn],n,m,ex,ey;
struct h{
int first[MOD],tot,nxt[S];
ll state[S],ans[S];
void init(){
memset(first,,sizeof(first));
tot=;
}
void insert(ll x,ll num){
for(int i=first[x%MOD];i;i=nxt[i]){
if(state[i]==x){
ans[i]+=num;
return;//!!!
}
}
state[++tot]=x;ans[tot]=num;
nxt[tot]=first[x%MOD];first[x%MOD]=tot;
}
}f[];
void decode(ll x){
for(int i=m;i>=;i--){
c[i]=x&;
x>>=;
}
}
int vis[maxn];//
ll encode(){
for(int i=;i<=;i++)vis[i]=;
int cnt=;ll x=;
for(int i=;i<=m;i++){
if(!c[i]){x<<=;continue;}
if(!vis[c[i]])vis[c[i]]=++cnt;
x=(x<<)|vis[c[i]];
}
return x;
}
void solve(int cur,int x,int y){
for(int k=;k<=f[cur^].tot;k++){
decode(f[cur^].state[k]);
int left=c[y-],up=c[y];
ll ans=f[cur^].ans[k];
if(left&&up){
if(left==up){
if(x==ex&&y==ey){
c[y-]=c[y]=;
f[cur].insert(encode(),ans);
}
}
else{
c[y-]=c[y]=;
for(int i=;i<=m;i++)if(c[i]==left)c[i]=up;
f[cur].insert(encode(),ans);
}
}
else if(left||up){
int now=left|up;
if(map[x+][y]){
c[y-]=now;c[y]=;
f[cur].insert(encode(),ans);
}
if(map[x][y+]){
c[y-]=;c[y]=now;
f[cur].insert(encode(),ans);
}
}
else{
if(map[x+][y]&&map[x][y+]){
c[y-]=c[y]=;
f[cur].insert(encode(),ans);
}
}
}
}
char s[maxn];
int main(){
scanf("%d%d",&n,&m);
memset(map,,sizeof(map));
ex=ey=;
for(int i=;i<=n;i++){
scanf("%s",s+);
for(int j=;j<=m;j++)if(s[j]=='.'){
map[i][j]=;//
ex=i;ey=j;
}
else map[i][j]=;
}
if(!ex){printf("0\n");return ;}
int cur=;
f[].init();f[].insert(,);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(map[i][j])cur^=,f[cur].init(),solve(cur,i,j);
}
for(int j=;j<=f[cur].tot;j++)f[cur].state[j]>>=;
}
ll ans=;
for(int i=;i<=f[cur].tot;i++)ans+=f[cur].ans[i];
printf("%lld\n",ans);
return ;
}
【Ural】1519. Formula 1 插头DP的更多相关文章
- 【BZOJ1814】Ural 1519 Formula 1 插头DP
[BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...
- bzoj1814 Ural 1519 Formula 1(插头dp模板题)
1814: Ural 1519 Formula 1 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 924 Solved: 351[Submit][Sta ...
- 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 ...
- 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 ...
- bzoj 1814: Ural 1519 Formula 1 插头dp经典题
用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. #include<iostream> #include<cstdio> #include<cstr ...
- 【BZOJ1814】Ural 1519 Formula 1 (插头dp)
[BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...
- ural 1519 Formula 1(插头dp)
1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...
随机推荐
- VMware12 pro装unlocker207补丁后依然没有apple mac选项,问题解决
把VMware所有的服务先停止,任务管理器里面的也停止.然后再安装unlocker207补丁就行了.亲测.
- 4th 课堂SCRM会议旁观记录
项目名称:基于C#的连连看设计 小组名称:待定 小组成员:张政.张金生.武志远.李权 Master:张政 项目已完成部分: 现阶段已经实现了一定的功能,可以运行使用,进行第一关的游戏. 今天计划要完成 ...
- Django之ORM其他骚操作
Django ORM执行原生SQL # extra # 在QuerySet的基础上继续执行子语句 # extra(self, select=None, where=None, params=None, ...
- apache常用的两种工作模式 prefork和worker
apache作为现今web服务器用的最广泛也是最稳定的开源服务器软件,其工作模式有许多中,目前主要有两种模式:prefork模式和worker模式 一.两种模式 prefork模式: prefork是 ...
- 第100天:CSS3中animation动画详解
CSS3属性中有关于制作动画的三个属性:Transform,Transition,Animation: 一.Animation定义动画 CSS3的Animation是由“keyframes”这个属性来 ...
- HDU4473_Exam
很考验智商的一个题目,赛后看完别人的题解后秒懂了. 首先定义一个函数f(x)表示a,b的有序组合情况数使得a*b为x的一个约数. 现在给定你一个n,要你求出f(1)+f(2)+……+f(n): 题目智 ...
- bzoj1390 [CEOI2008] Fence
题意 给出n个白点和m个黑点.现在你需要选择一些白点把黑点圈起来.每有一个黑点不能被选出的白点组成的凸包包含就需要付出111的代价,每选出一个白点就需要付出20的代价.要求最小化代价之和 n,m< ...
- 【Java并发编程】之三:线程挂起、恢复与终止的正确方法
挂起和恢复线程 Thread 的API中包含两个被淘汰的方法,它们用于临时挂起和重启某个线程,这些方法已经被淘汰,因为它们是不安全的,不稳定的.如果在不合适的时候挂起线程(比如,锁定共享资源时), ...
- [COGS1000]伊吹萃香 最短路
1000. [東方S2] 伊吹萃香 输入文件:suika.in 输出文件:suika.out 简单对比 时间限制:1 s 内存限制:128 MB Problem 4 伊吹萃香(suika. ...
- 【51Nod1258】序列求和V4(FFT)
[51Nod1258]序列求和V4(FFT) 题面 51Nod 多组数据,求: \[Ans=\sum_{i=1}^ni^k,n\le 10^{18},k\le50000\] 题解 预处理伯努利数,时间 ...