bzoj1814: Ural 1519 Formula 1 动态规划 插头dp
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的更多相关文章
- bzoj1814 Ural 1519 Formula 1(插头DP)
对插头DP的理解还不是很透彻. 先说一下肤浅的理解吧. 插头DP使用范围:指数级复杂度,且适用于解决网格图连通性问题,如哈密顿回路等问题.插头一般指每相邻2个网格的接口. 题目难度:一般不可做. 使用 ...
- 插头DP讲解+[BZOJ1814]:Ural 1519 Formula 1(插头DP)
1.什么是插头$DP$? 插头$DP$是$CDQ$大佬在$2008$年的论文中提出的,是基于状压$D$P的一种更高级的$DP$多用于处理联通问题(路径问题,简单回路问题,多回路问题,广义回路问题,生成 ...
- 【BZOJ1814】Ural 1519 Formula 1 (插头dp)
[BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...
- URAL 1519 Formula 1(插头DP,入门题)
Description Background Regardless of the fact, that Vologda could not get rights to hold the Winter ...
- ural 1519 Formula 1(插头dp)
1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...
- URAL 1519 Formula 1 (插头DP,常规)
题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法? 思路: 本来是很基础的题,顿时不知道进入了哪个坑.这篇插头DP的 ...
- bzoj 1814: Ural 1519 Formula 1【插头dp】
设f[i][j][s]为轮廓线推到格子(i,j),状态为s的方案数 括号表示一段线的左端和右端,表示成左括号和右括号,状压的时候用1和2表示,0表示已经闭合 下面的蓝线是黄色格子的轮廓线,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 ...
随机推荐
- 【译】第十篇 Replication:故障排除
本篇文章是SQL Server Replication系列的第十篇,详细内容请参考原文. 复制故障排除是一项艰巨的任务.在任何复制设置中,都涉及到很多移动部件,而可用的工具并不总是很容易识别问题.Th ...
- nginx+tomat https ssl 部署 完美解决方案
关于nginx+tomcat https的部署之前网上一直有2种说法: 1.nginx和tomcat都要部署ssl证书 2.nginx部署ssl证书,tomcat增加ssl支持 在实际的部署过程中ng ...
- gnome桌面无法使用笔记本的触摸板
原来使用ubuntu的时候,升级了gnome之后触摸板就不能用了,不能说不能用了,应该是自己不会配置然后不好用了,具体状况如是,可以在登录界面gdm使用触摸板以及点击,但是进入桌面之后就不能点击了.后 ...
- container_of分析【转】
转自:http://blog.csdn.net/tigerjibo/article/details/8299589 1.container_of宏 1> Container_of在Linux内核 ...
- Mysql Limit操作
oracle : || mysql: contact contact_ws 拼接 Font Size: Large | Medium | Small select * from tabl ...
- redis tutorail
命令 set get incr expire 秒 ttl -1 不会过期 list : lpush rpush lpop rpop lrange llen se ...
- 向SQL Server 现有表中添加新列并添加描述.
注: sql server 2005 及以上支持. 版本估计是不支持(工作环境2005,2008). 工作需要, 需要向SQL Server 现有表中添加新列并添加描述. 从而有个如下存储过程. (先 ...
- 触发器中的inserted表和deleted表
触发器语句中使用了两种特殊的表:deleted 表和 inserted 表.Microsoft? SQL Server 2000 自动创建和管理这些表.可以使用这两个临时的驻留内存的表测试某些数据修改 ...
- 树莓派3B安装远程
步骤1:树莓派3安装 RDP SERVER 及VNC SERVER sudo apt-get install -y tightvncserver sudo vncserver 最后才知道一定要加上VN ...
- 关于jedis2.4以上版本的连接池配置,及工具类
jedis.propertise 注意以前版本的maxAcitve和maxWait有所改变,JVM根据系统环境变量ServerType中的值 取不同的配置,实现多环境(测试环境.生产环境)集成. re ...