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. MUI上拉加载下拉刷新

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. web项目打包后在代码中获取资源文件

    在web项目里面,有时代码里面需要引用一些自定义的配置文件,这些配置文件如果放在类路径下,项目经过打包后使用的相对路径也会发生变化,所以以下给出了三种解决方案. 一.properties下配置 在类路 ...

  3. Hibernate5笔记1--Hibernate简介和第一个程序

    Hibernate简介: Hibernate是一个开放源代码的ORM(对象关系映射)框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hib ...

  4. flask基础之app初始化(四)

    前言 flask的核心对象是Flask,它定义了flask框架对于http请求的整个处理逻辑.随着服务器被启动,app被创建并初始化,那么具体的过程是这样的呢? 系列文章 flask基础之安装和使用入 ...

  5. 用Qemu模拟vexpress-a9 (一) --- 搭建Linux kernel调试环境【转】

    转自:http://www.cnblogs.com/pengdonglin137/p/5023342.html#_label2 阅读目录(Content) 环境介绍: 下载Linux内核 安装arm的 ...

  6. Dapper实用教程

    Dapper是什么? Dpper是一款.Net平台简单(Simple)的对象映射库,并且Dapper拥有着“微型ORM之王”的称号.就速度而言与手写ADO.NET SqlDateReader相同.OR ...

  7. Mac下破解intellij IDEA 2018

    一.在进入下面网站下载破解补丁 http://idea.lanyus.com/ 二.在“应用程序”中找到已经安装的IntelliJ IDEA,在app上右键,选择“显示包内容”,如下图: 将下载的破解 ...

  8. github 优秀的开源项目

    https://github.com/wlcaption/AndroidMarket---- 这是手机应用商店,包含应用的下载,用户中心等内容 https://github.com/wlcaption ...

  9. CNN细节

    1.各层作用 输入层 输入层是整个神经网络的输入,一般代表的是图片的像素矩阵(一般为三维矩阵,即像素x像素x通道) 卷积层 每一层卷积都会提取数据特征,再经过组合和抽象形成更高阶的特征. 池化层 保留 ...

  10. Codeforces 793C - Mice problem(几何)

    题目链接:http://codeforces.com/problemset/problem/793/C 题目大意:给你一个捕鼠器坐标,和各个老鼠的的坐标以及相应坐标的移动速度,问你是否存在一个时间点可 ...