Link:

POJ 1739 传送门

Solution:

这题除了一开始的预处理,基本上就是插头$dp$的模板题了

由于插头$dp$求的是$Hamilton$回路,而此题有起点和终点的限制

于是可以构造一条$[n,1]->[n+2,1]->[n+2,m]->[n,m]$的路径,正好只添加一条$S->T$的路径

接下来就是插头$dp$的模板了

推荐三篇文章,看完基本上就懂插头$dp$了吧,

litble:https://blog.csdn.net/litble/article/details/79369147

yhzq:远航之曲博客

陈丹琦论文:http://www.doc88.com/p-9009338580746.html

可以发现,插头$dp$其实就是对于当前已枚举部分和未枚举部分的轮廓线的状压$dp$

注意每枚举过一行要将所有状态左移一位(下一行会多出来一个状态位)

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <utility>
#include <vector> using namespace std;
typedef long long ll; const int INF=0x3f3f3f3f,MAXN=,MAX_State=3e5+,MAX_Hash=3e5;
int n,m,pre,cur,dat[MAXN][MAXN];
int st[][MAX_State],st_cnt[],bit[];
ll res[][MAX_State],sum=; struct edge{int to,next;}e[MAX_State];
int hs[MAX_State],hs_cnt=;
void ins(int now,ll x)
{
int p=now%MAX_Hash;
for(int i=hs[p];i;i=e[i].next) //Hash时最好使用链式前向星
if(st[cur][e[i].to]==now){res[cur][e[i].to]+=x;return;}
st_cnt[cur]++; e[++hs_cnt].to=st_cnt[cur];
e[hs_cnt].next=hs[p];
hs[p]=hs_cnt; st[cur][st_cnt[cur]]=now;res[cur][st_cnt[cur]]=x;
} void plugDP()
{
sum=st[cur][]=cur=; //注意初始化的顺序
st_cnt[cur]=res[cur][]=; for(int i=;i<=n;i++)
{
for(int j=;j<=st_cnt[cur];j++) //左移一位
st[cur][j]<<=;
for(int j=;j<=m;j++)
{
hs_cnt=;memset(hs,,sizeof(hs));
pre=cur;cur^=;st_cnt[cur]=;
for(int k=;k<=st_cnt[pre];k++)
{
int now=st[pre][k];ll x=res[pre][k];
ll dw=(now>>bit[j-])&,rt=(now>>bit[j])&;
ll numd=<<bit[j-],numr=<<bit[j]; if(!dat[i][j] && !dw && !rt) ins(now,x);
else if(!dw && !rt && dat[i+][j] && dat[i][j+])
ins(now+numd+*numr,x);
else if(!dw && rt)
{
if(dat[i][j+]) ins(now,x);
if(dat[i+][j]) ins(now-rt*numr+rt*numd,x);
}
else if(dw && !rt)
{
if(dat[i+][j]) ins(now,x);
if(dat[i][j+]) ins(now-dw*numd+dw*numr,x);
}
else if(dw== && rt==)
{
int flag=;
for(int l=j+;l<=m;l++)
{
if(((now>>bit[l])&)==) flag++;
if(((now>>bit[l])&)==) flag--;
if(!flag){ins(now-numd-numr-(<<bit[l]),x);break;}
}
}
else if(dw== && rt==)
{
int flag=-;
for(int l=j-;l>=;l--)
{
if(((now>>bit[l])&)==) flag++;
if(((now>>bit[l])&)==) flag--;
if(!flag){ins(now-*numd-*numr+(<<bit[l]),x);break;}
}
}
else if(dw== && rt==) ins(now-*numd-numr,x);
else if(dw== && rt== && i==n && j==m) sum+=x;
}
}
}
} int main()
{
for (int i=;i<;i++)
bit[i]=i<<;
while(~scanf("%d%d",&n,&m) && n && m)
{
memset(dat,,sizeof(dat));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
char ch=getchar();
while(ch!='.' && ch!='#') ch=getchar();
if(ch=='.') dat[i][j]=;
}
n+=;dat[n-][]=dat[n-][m]=; //预处理
for(int i=;i<=m;i++) dat[n][i]=; plugDP();printf("%lld\n",sum);
}
return ;
}

Review:

做的时候犯的丝帛错误:

1、对变量初始化的先后顺序要注意!!!

EX:$cur=0$要在$st[cur][1]$之前初始化

2、哈希表最好用链式前向星实现

用$vector$时TLE了,可能是$vector.clear()$的时间太长了?

链式前向星的一大优点就是重复使用时不用清空数组,只要$tot=0$即可

3、左移、右移比$==$优先级高,但位与、位或比$==$优先级低!!

[POJ 1739] Tony's Tour的更多相关文章

  1. POJ 1739 Tony's Tour(插头DP)

    Description A square township has been divided up into n*m(n rows and m columns) square plots (1< ...

  2. POJ 1739 Tony's Tour (DP)

    题意:从左下角到右下角有多少种走法. 析:特殊处理左下角和右下角即可. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000 ...

  3. POJ 1739 Tony's Tour (插头DP,轮廓线DP)

    题意:给一个n*m的矩阵,其中#是障碍格子,其他则是必走的格子,问从左下角的格子走到右下角的格子有多少种方式. 思路: 注意有可能答案是0,就是障碍格子阻挡住了去路. 插头DP有两种比较常见的表示连通 ...

  4. 【POJ】1739 Tony's Tour

    http://poj.org/problem?id=1739 题意:n×m的棋盘,'#'是障碍,'.'是空白,求左下角走到右下角且走过所有空白格子的方案数.(n,m<=8) #include & ...

  5. 【POJ】【1739】Tony's Tour

    插头DP 楼教主男人八题之一! 要求从左下角走到右下角的哈密顿路径数量. 啊嘞,我只会求哈密顿回路啊……这可怎么搞…… 容易想到:要是把起点和重点直接连上就变成一条回路了……那么我们就连一下~ 我们可 ...

  6. POJ 1739:Tony's Tour

    Description A square township has been divided up into n*m(n rows and m columns) square plots (1< ...

  7. 【poj1739】 Tony's Tour

    http://poj.org/problem?id=1739 (题目链接) 题意 给出一个n*m的地图,有些是障碍.问从左下角走遍所有非障碍格子一次且仅一次最终到达右下角的路径方案数. Solutio ...

  8. POJ 1739

    楼教主男人八题之一... 题目大意: 求从左下角经过所有非障碍点一次到达右下角的方案数 这里不是求回路,但是我们可以考虑,在最下面一行再增加一行,那么就可以当做求此时左下角到右下角的回路总数,那么就转 ...

  9. 插头DP专题

    建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...

随机推荐

  1. 如何抓取开了gzip的网页

    有时候用 file_get_contents() 函数抓取网页会发生乱码现象.有两个原因会导致乱码,一个是编码问题,一个是目标页面开了Gzip. 编码问题好办,把抓取到的内容转下编码即可($conte ...

  2. readelf用法小记

    By francis_hao    Feb 14,2017 显示ELF文件的信息 用法概述 readelf和objdump类似,不过,readelf会显示更详细的信息,而且独立于BFD库,因此当BFD ...

  3. webpack 的第三方库分离并持久化缓存

    我们常常需要在浏览器缓存一些稳定的资源,如第三方库等.要达到这个目标,只需要两步: 1.提取出“稳定的资源”: 2.提供稳定的文件hash . 处理后的出的文件就像这样子: app.1w3ad4q4. ...

  4. 转:java 帐号激活与忘记密码 实例

    原文链接:http://endual.iteye.com/blog/1613679 一.帐户激活   在 很多时候,在某些网站注册一个用户之后,网站会给这个用户注册时填写的email地址发送一封帐户激 ...

  5. 图论:KM算法

    如果,将求二分图的最大匹配的所有匹配边的权重看做1 那么用匈牙利算法求二分图的最大匹配的问题也可以看成求二分图的最大权匹配 如果边权是特例,我们就要使用KM算法来做了 这个算法其实还是比较难的,会用就 ...

  6. bzoj1833: [ZJOI2010]count 数字计数 && codevs1359 数字计数

    bzoj1833 codevs1359 这道题也是道数位dp 因为0有前导0这一说卡了很久 最后发现用所有位数减1~9的位数就okay.....orzczl大爷 其他就跟51nod那道统计1出现次数一 ...

  7. DP+贪心水题合集_C++

    本文含有原创题,涉及版权利益问题,严禁转载,违者追究法律责任 本次是最后一篇免费的考试题解,以后的考试题目以及题解将会以付费的方式阅读,题目质量可以拿本次作为参考 本来半个月前就已经搞得差不多了,然后 ...

  8. 渗透测试中如何科学地使用V*P*N

    环境说明 Windows7 虚拟机,作为VPN网关,负责拨VPN.VPN可以直接OPENVPN,也可以使用ShadowSocks+SSTap. Kali 虚拟机, 渗透测试工作机 配置步骤 Windo ...

  9. pychart

    Pychart PyChart is a Python library for creating high quality Encapsulated Postscript, PDF, PNG, or ...

  10. [Leetcode Week5]Word Ladder

    Word Ladder题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder/description/ Description Give ...