POJ 1739 Tony's Tour
来源:互联网 发布:网络誉情内参 编辑:程序博客网 时间:2024/06/08 17:01
题意:给定n*m的带障碍格子图,求从左下角走到右下角的哈密顿路的总数。
题解:更进一步的插头DP,主要解法可以参照我的上篇日志:http://blog.csdn.net/tmeteorj/article/details/8635090。
改动之处在于单向插头,上篇中用01和10分别代表左右括号,这道题则需要加11作为单向括号(因为它在括号序列状态中是没有与之匹配的括号的)
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAX=10007;typedef long long LL;struct HT{ int head,hash[MAX],nxt[MAX]; LL cnt[MAX]; void init() { head=-1; memset(hash,-1,sizeof(hash)); memset(nxt,-1,sizeof(nxt)); memset(cnt,0,sizeof(cnt)); } void insert(int st,LL ct) { LL pos=st%MAX; LL ad=1; while(hash[pos]!=st&&hash[pos]!=-1) { pos+=ad*ad; ad++; if(pos>=MAX)pos%=MAX; } if(hash[pos]==-1) { hash[pos]=st; cnt[pos]=ct; nxt[pos]=head; head=pos; } else cnt[pos]+=ct; }} dp[2];int n,m;char mp[14][14];int findright(int st,int pos){ int tp,p=pos; for(int dep=1; dep!=0; p+=1) { tp=((st>>((m-p+1)*2))&3)%4; switch(tp) { case 0: break; case 1: dep++; break; case 2: dep--; break; } if(dep==0) break; } return 3<<((m-p+1)*2);}int findleft(int st,int pos){ int tp,p=pos; for(int dep=1; dep!=0; p-=1) { tp=((st>>((m-p+1)*2))&3)%4; switch(tp) { case 0: break; case 1: dep--; break; case 2: dep++; break; } if(dep==0) break; } return 3<<((m-p+1)*2);}LL getans(int fg){ LL pos=0,ad=1; while(dp[fg].hash[pos]!=0&&dp[fg].hash[pos]!=-1) { pos+=ad*ad; ad++; if(pos>=MAX)pos%=MAX; } if(dp[fg].hash[pos]==-1) { return 0ll; } else return dp[fg].cnt[pos];}int main(){ while(scanf("%d%d",&n,&m),n||m) { for(int i=1; i<=n; i++)scanf(" %s",mp[i]+1); int fg1=1,fg2,ex,ey; fg1=0,fg2=1; dp[fg2].init(); dp[fg2].insert(0,1ll); for(int i=1; i<=n; i++) { fg1=!fg1; fg2=!fg2; dp[fg2].init(); for(int tp=dp[fg1].head; tp!=-1; tp=dp[fg1].nxt[tp]) { if(dp[fg1].hash[tp]&3) continue; dp[fg2].insert(dp[fg1].hash[tp]>>2,dp[fg1].cnt[tp]); } for(int j=0; j<m; j++) { fg1=!fg1; fg2=!fg2; dp[fg2].init(); int a=3<<(2*(m-j)),b=3<<(2*(m-j-1)); for(int pos=dp[fg1].head; pos!=-1; pos=dp[fg1].nxt[pos]) { int st=dp[fg1].hash[pos]; LL ct=dp[fg1].cnt[pos]; int x=((st&a)>>(2*(m-j)))%4,y=((st&b)>>(2*(m-j-1)))%4; if(i==n) { if(j==0) { if(y) dp[fg2].insert(st&(~b)|findright(st,j+3),ct); else dp[fg2].insert(st|b,ct); continue; } else if(j==m-1) { if((x==3||y==3)&(x!=3||y!=3)) dp[fg2].insert(st&(~a)&(~b),ct); continue; } } if(mp[i][j+1]=='#') { if(x||y) continue; dp[fg2].insert(st,ct); } else if(x) { if(y) { if(x==1&&y==1) dp[fg2].insert((st&(~a)&(~b))^findright(st,j+3),ct); else if(x==2&&y==1) dp[fg2].insert(st&(~a)&(~b),ct); else if(x==2&&y==2) dp[fg2].insert((st&(~a)&(~b))^findleft(st,j),ct); else if(x==3) dp[fg2].insert((st&(~a)&(~b))|findright(st,j+3),ct); else if(y==3) dp[fg2].insert((st&(~a)&(~b))|findleft(st,j),ct); } else { dp[fg2].insert(st,ct); dp[fg2].insert(st&(~a)|(x<<(2*(m-j-1))),ct); } } else if(y) { dp[fg2].insert(st,ct); dp[fg2].insert(st&(~b)|(y<<(2*(m-j))),ct); } else dp[fg2].insert(st|(1<<(2*(m-j)))|(2<<(2*(m-j-1))),ct); } } } printf("%lld\n",getans(fg2)); } return 0;}
- poj 1739 Tony's Tour
- poj 1739 Tony's Tour
- POJ 1739 Tony's Tour
- POJ 1739 Tony's Tour
- 【POJ 1739】Tony's Tour
- POJ 1739 Tony's Tour
- POJ-1739:Tony's Tour
- poj 1739 Tony's Tour 插头dp
- poj 1739 Tony's Tour 插头dp
- POJ 1739 Tony's Tour (插头DP)
- poj 1739 Tony's Tour(插头dp)
- POJ 1739 Tony's Tour 插头DP
- poj 1739 Tony's Tour 插头dp
- POJ 1739 Tony's Tour 笔记
- POJ 1739 Tony's Tour 解题报告(插头DP)
- POJ - 1739 Tony's Tour (单回路插头dp)
- poj 1739 Tony's Tour 插头dp模板题
- Tony's Tour poj1739
- mysql 时间格式化
- win7里面可以查看完整网络映射,xp里面有没有办法实现?
- ASP.NET使用NPOI类库导出Excel(收藏)
- Android init.rc BOOTCLASSPATH
- python下的事件驱动编程
- POJ 1739 Tony's Tour
- 友元
- 目录下文件后缀的更改
- excel数据格式问题
- Eclipse NDK 配置
- 单个JSP页面中实现查询和删除数据实例
- android在点击EditText的时候始终不弹出软件键盘
- flash基本操作二-库面板和元件创建
- android中数据库查询优化方法