http://acm.timus.ru/problem.aspx?space=1&num=1519

题目描述

一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数。

输入

The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.

输出

You should output the desired number of ways. It is guaranteed, that it does not exceed 2^63-1.

样例输入

4 4
**..
....
....
....

样例输出

2

直接写时间复杂度过不了,直接写了个dp里面有很多无用状态,剪枝一下(存下一个的有用状态)就行了。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
#define LL long long
int n,m;
char ch[][]={};
int id[][]={};
LL shu[]={};
map< int,LL >f[];
inline int getit(int z,int i){return (z/shu[i])%;}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%s",ch[i]+);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)id[i][j]=(i-)*m+j;
shu[]=;int ff=;
for(int i=;i<=m+;i++)shu[i]=shu[i-]*;
if(ch[][]=='.'){f[][+*]=;ff=;}
else f[][]=;
int mx=shu[m+]*,now,nex,fla,z,x,y; LL val;
for(int i=;i<=n;i++){
for(int j=;j<m;j++){
if(i==n&&j==m-)break;
now=id[i][j];nex=now+;fla=;
if(ch[i][j+]!='.')fla=;
if(ch[i][j]==)ff=;
for(int w=ff;w<mx;w++){
val=f[now][w];
if(val==)continue;
x=getit(w,j+);y=getit(w,j+);
if(fla){
if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
f[nex][z]+=val;
}
continue;
}
if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
f[nex][z]+=val;
}
else if(x==||y==){
z=w+(x+y-x)*shu[j+]+(-y)*shu[j+];
f[nex][z]+=val;
z=w+(-x)*shu[j+]+(x+y-y)*shu[j+];
f[nex][z]+=val;
}
else if(x==y){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
int zz,zzz;
if(x==){
zz=-;zzz=j+;
while(zz!=){
++zzz;
if(zzz>m+)break;
if(getit(w,zzz)==)--zz;
if(getit(w,zzz)==) ++zz;
}
if(zz!=)continue;
z=z+(-)*shu[zzz];
}
else{
zz=;zzz=j+;
while(zz!=){
--zzz;
if(zzz>m+)break;
if(getit(w,zzz)==)--zz;
if(getit(w,zzz)==) ++zz;
}
if(zz!=)continue;
z=z+(-)*shu[zzz];
}
f[nex][z]+=val;
}
else if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
f[nex][z]+=val;
}
}
}
if(i==n)break;
now=i*m;nex=now+;
fla=;
if(ch[i+][]!='.')fla=;
if(ch[i][m]=='.')ff=;
for(int w=ff;w<mx;++w){
val=f[now][w];
if(val==)continue;
if(getit(w,m+)!=)continue;
x=getit(w,);
if(fla){
if(!x){
z=(w%shu[m+]-x)*; f[nex][z]+=val;
}
continue;
}
if(x==){
z=(w%shu[m+]-x)*;
z=z+;f[nex][z]+=val;
z=z+;f[nex][z]+=val;
}
else if(x==){
z=(w%shu[m+]-x)*++*;
f[nex][z]+=val;
}
}
}
printf("%lld\n",f[n*m-][shu[m]*+shu[m+]*]);
return ;
}

原代码

更改之后不开O2跑12*12的无障碍图需要快2s,大概是用map复杂度加了个log的锅……不想写hash……

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
#define LL long long
int n,m;
char ch[][]={};
int id[][]={};
int cun[][]={},tot[]={};
LL shu[]={};
map< int,LL >f[];
inline int getit(int z,int i){return (z/shu[i])%;}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%s",ch[i]+);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)id[i][j]=(i-)*m+j;
shu[]=;
for(int i=;i<=m+;i++)shu[i]=shu[i-]*;
if(ch[][]=='.'){f[][+*]=;tot[]=;cun[][]=+*;}
else { f[][]=;tot[]=;cun[][]=;}
int now,nex,fla,z,x,y,id1,id2; LL val;
for(int i=;i<=n;i++){
for(int j=;j<m;j++){
if(i==n&&j==m-)break;
now=id[i][j];nex=now+;fla=;
if(ch[i][j+]!='.')fla=;
id1=id[i][j]&;id2=id1^;
tot[id2]=;
for(int k=;k<=tot[id1];k++){
int w=cun[id1][k];
val=f[now][w];
if(val==)continue;
x=getit(w,j+);y=getit(w,j+);
if(fla){
if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
continue;
}
if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==||y==){
z=w+(x+y-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
z=w+(-x)*shu[j+]+(x+y-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==y){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
int zz,zzz;
if(x==){
zz=-;zzz=j+;
while(zz!=){
++zzz;
if(zzz>m+)break;
if(getit(w,zzz)==)--zz;
if(getit(w,zzz)==) ++zz;
}
if(zz!=)continue;
z=z+(-)*shu[zzz];
}
else{
zz=;zzz=j+;
while(zz!=){
--zzz;
if(zzz>m+)break;
if(getit(w,zzz)==)--zz;
if(getit(w,zzz)==) ++zz;
}
if(zz!=)continue;
z=z+(-)*shu[zzz];
}
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
}
}
if(i==n)break;
now=i*m;nex=now+;
fla=;
if(ch[i+][]!='.')fla=;
id1=id[i][m]&;id2=id1^;
tot[id2]=;
for(int k=;k<=tot[id1];++k){
int w=cun[id1][k];
val=f[now][w];
if(val==)continue;
if(getit(w,m+)!=)continue;
x=getit(w,);
if(fla){
if(!x){
z=(w%shu[m+]-x)*;
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
continue;
}
if(x==){
z=(w%shu[m+]-x)*;
z=z+; if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
z=z+; if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==){
z=(w%shu[m+]-x)*++*;
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
}
}
printf("%lld\n",f[n*m-][shu[m]*+shu[m+]*]);
return ;
}

去掉无用状态后

用map竟然过了……不过要注意一下最后输出的是最后一个可行位置的答案,很有可能最后一个点不是可行的,被坑了一下QAQ

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
#define LL long long
int n,m;
char ch[][]={};
int id[][]={};
int cun[][]={},tot[]={};
LL shu[]={};
map< int,LL >f[];
inline int getit(int z,int i){return (z/shu[i])%;}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%s",ch[i]+);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)id[i][j]=(i-)*m+j;
int idx=,idy=;
for(int i=;i<=n;i++)for(int j=;j<=m;j++)if(ch[i][j]=='.'){idx=i;idy=j;}
if(idy<=){printf("0\n");return ;}
shu[]=;
for(int i=;i<=m+;i++)shu[i]=shu[i-]*;
if(ch[][]=='.'){f[][+*]=;tot[]=;cun[][]=+*;}
else { f[][]=;tot[]=;cun[][]=;}
int now,nex,fla,z,x,y,id1,id2; LL val;
for(int i=;i<=idx;i++){
for(int j=;j<m;j++){
if(i==n&&j==m-)break;
now=id[i][j];nex=now+;fla=;
if(ch[i][j+]!='.')fla=;
id1=id[i][j]&;id2=id1^;
tot[id2]=;
for(int k=;k<=tot[id1];k++){
int w=cun[id1][k];
val=f[now][w];
if(val==)continue;
x=getit(w,j+);y=getit(w,j+);
if(fla){
if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
continue;
}
if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==||y==){
z=w+(x+y-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
z=w+(-x)*shu[j+]+(x+y-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==y){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
int zz,zzz;
if(x==){
zz=-;zzz=j+;
while(zz!=){
++zzz;
if(zzz>m+)break;
if(getit(w,zzz)==)--zz;
if(getit(w,zzz)==) ++zz;
}
if(zz!=)continue;
z=z+(-)*shu[zzz];
}
else{
zz=;zzz=j+;
while(zz!=){
--zzz;
if(zzz>m+)break;
if(getit(w,zzz)==)--zz;
if(getit(w,zzz)==) ++zz;
}
if(zz!=)continue;
z=z+(-)*shu[zzz];
}
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==&&y==){
z=w+(-x)*shu[j+]+(-y)*shu[j+];
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
}
}
if(i==n)break;
now=i*m;nex=now+;
fla=;
if(ch[i+][]!='.')fla=;
id1=id[i][m]&;id2=id1^;
tot[id2]=;
for(int k=;k<=tot[id1];++k){
int w=cun[id1][k];
val=f[now][w];
if(val==)continue;
if(getit(w,m+)!=)continue;
x=getit(w,);
if(fla){
if(!x){
z=(w%shu[m+]-x)*;
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
continue;
}
if(x==){
z=(w%shu[m+]-x)*;
z=z+; if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
z=z+; if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
else if(x==){
z=(w%shu[m+]-x)*++*;
if(f[nex][z]==)cun[id2][++tot[id2]]=z;
f[nex][z]+=val;
}
}
}
printf("%lld\n",f[(idx-)*m+idy-][shu[idy]*+shu[idy+]*]);
return ;
}

这绝对是最后一版了

cnblog什么毛病啊……给代码加了标题如果要复制代码标题就到代码末尾了……mdzz

bzoj1814: Ural 1519 Formula 1 动态规划 插头dp的更多相关文章

  1. bzoj1814 Ural 1519 Formula 1(插头DP)

    对插头DP的理解还不是很透彻. 先说一下肤浅的理解吧. 插头DP使用范围:指数级复杂度,且适用于解决网格图连通性问题,如哈密顿回路等问题.插头一般指每相邻2个网格的接口. 题目难度:一般不可做. 使用 ...

  2. 插头DP讲解+[BZOJ1814]:Ural 1519 Formula 1(插头DP)

    1.什么是插头$DP$? 插头$DP$是$CDQ$大佬在$2008$年的论文中提出的,是基于状压$D$P的一种更高级的$DP$多用于处理联通问题(路径问题,简单回路问题,多回路问题,广义回路问题,生成 ...

  3. 【BZOJ1814】Ural 1519 Formula 1 (插头dp)

    [BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...

  4. URAL 1519 Formula 1(插头DP,入门题)

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

  5. ural 1519 Formula 1(插头dp)

    1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...

  6. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

  7. URAL 1519 Formula 1 (插头DP,常规)

    题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法? 思路: 本来是很基础的题,顿时不知道进入了哪个坑.这篇插头DP的 ...

  8. bzoj 1814: Ural 1519 Formula 1【插头dp】

    设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数 括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合 下面的蓝线是黄色格子的轮廓线,dp转移要把 ...

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

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

随机推荐

  1. 【方法】jQuery无插件实现 鼠标拖动切换图片/内容 功能

    前言 我就想随便叨逼叨几句,爱看就看几句,不爱看就直接跳过看正文就好啦~ 这个方法是仿写页面时我自己研究出来,可能有比我更简单的方法. 但我不管,因为我没查我不知道,我就觉得我的最好啦,耶耶耶~ 效果 ...

  2. Java 8 Lambda表达式,让你的代码更简洁

    Lambda表达式是Java 8一个非常重要的新特性.它像方法一样,利用很简单的语法来定义参数列表和方法体.目前Lambda表达式已经成为高级编程语言的标配,像Python,Swift等都已经支持La ...

  3. WIN下的CMD下载命令

    certutil -urlcache -split -f 远程地址 本地保存的文件跑径与文 件名 # 如里不写本地文 件名与路径名, 会自动跟远程文 件名相同, 并保存到当前目 录下 另一个是: bi ...

  4. Pytorch数据变换(Transform)

    实例化数据库的时候,有一个可选的参数可以对数据进行转换,满足大多神经网络的要求输入固定尺寸的图片,因此要对原图进行Rescale或者Crop操作,然后返回的数据需要转换成Tensor如: import ...

  5. 3->集群架构主机克隆教程

    centos7系统集群主机克隆: 有道笔记链接地址

  6. Java KeyStore 用命令生成keystore文件自己生成证书,简介

    1.生成keyStore文件 在命令行下执行以下命令: Shell代码 收藏代码 keytool -genkey -validity 36000 -alias www.zlex.org -keyalg ...

  7. SQL Server中的快捷键

    新建查询:Ctrl + N 反撤销:Ctrl + Y 撤销:Ctrl + Z 查找:Ctrl + F 启动调试:Alt + F5 注释:Ctrl + K + C 取消注释:Ctrl + K + U 执 ...

  8. CCF CSP 201604-4 游戏

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201604-4 游戏 问题描述 小明在玩一个电脑游戏,游戏在一个n×m的方格图上进行,小明控制 ...

  9. 使用scss + react + webpack + es6实现幻灯片

    写在前面: 刚学习完慕课网里的一个幻灯片案例,自己加了刚学的react,两者结合.首先让大家看看效果 点击此处 你可以先用纯js实现上面的效果:我的github上的 JS代码 或者 观看慕课提供的课程 ...

  10. bzoj 1831

    思路:随便猜一猜填的数字是不下降的,反证很好证明,然后就没了.. #include<bits/stdc++.h> #define LL long long #define fi first ...