3125: CITY

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 486  Solved: 213
[Submit][Status][Discuss]

Description

小明和小华要参加NOI,踏上了去X市的火车。
小明望着窗外的田野,大楼,工厂缓缓后退,在思考着什么。
这时,对面的小华拿出手机对着他说:“看!我们在这个位置!”
小明望着手机上显示的地图,城市被接到分割成各个方块,而自己所在的点在慢慢移动。
他突然意识到自己甚至还没游历过这个自己所在的小城市,学校和家貌以及之间来回的道路似乎成了这个小城的唯一印象。
若我把它们全部走一圈,可能要仔细计划下吧……不,那么多方案,其实我应该早能做到了吧……小明在心里对自己说。
 

Input

第一行有两个数N, M表示地图被分割成N*M个块,接下来有N行,每行有M个字符。
 .  表示这个块可以通过
 - 表示这个块只可以左右通过
 | 表示这个块只可以上下通过
 # 表示这个块不能通过
(从每个块只能走到其上下左右相邻的四个块)
 

Output

一个数,表示小明把所以可以通过的块都经过且只经过一次并回到原地的方案数。
 

Sample Input

Sample 1
2 2
..
..

Sample 2
Input:
4 4
....
..-.
....
....

Sample Output

Output 1
1

Output 2
1

HINT

数据范围: 0 < N, M < 13 不保证答案在long 范围之内

Source

  联赛后第一次写题解……

  这道题可以说得上是插头DP裸题了,话说最早接触插头DP是在学基础状压的时候误打误撞看到了CDQ的论文,差点入坑,然而最后我还是得入一下。

  这道题比较特殊的就是‘-’ ‘|’这两个设定,但其实也很容易,我们只要在转移的时候进行特判,‘-’只能接左插头,‘|’只能接上插头。其余转移同理。但是要注意的是由于许多转移代码大体结构一样,可以直接复制粘贴,但是细节还是要去检查一下,我因为特判粘贴后位置改变却没发现调了两个小时。

 #include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 15
using namespace std;
int n,m,ma[N][N],zz,tot[];
char bb[N];
int xp[N],b[],dl[];
long long f[][],ans;
bool check(int x,int t,int sum)
{
if(sum<) return ;
if(x==m+)
return sum==;
if(b[t/xp[x]]==) return check(x+,t,sum+);
else if(b[t/xp[x]]==) return check(x+,t,sum-);
else return check(x+,t,sum);
}
int main()
{
int nn,mm;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",bb+);
for(int j=;j<=m;j++)
{
if(bb[j]=='.') ma[i][j]=,nn=i,mm=j;
else if(bb[j]=='-') ma[i][j]=,nn=i,mm=j;
else if(bb[j]=='|') ma[i][j]=,nn=i,mm=j;
}
}
xp[]=;
for(int i=;i<=m+;i++) xp[i]=xp[i-]*;
for(int i=;i<xp[m+];i++) b[i]=i%;
for(int i=;i<xp[m+];i++)
{
if(check(,i,))
{
zz++;
tot[zz]=i;
dl[i]=zz;
}
}
int now=,la=;
f[][]=;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
la^=,now^=;
memset(f[now],,sizeof(f[now]));
int p,q,x=xp[j-],y=xp[j],t;
for(int k=;k<=zz;k++)
{
p=b[tot[k]/x],q=b[tot[k]/y];
t=tot[k]-p*x-q*y;
if(ma[i][j])
{
if(!p&&!q)
{
if(ma[i][j]==&&dl[t+x+(y<<)]) f[now][dl[t+x+(y<<)]]+=f[la][k];
}
else if(!q)
{
if(ma[i][j]!=)
{
if(j!=m&&dl[t+(y<<(p-))]) f[now][dl[t+(y<<(p-))]]+=f[la][k];
if(i!=n&&ma[i][j]==&&dl[t+(x<<(p-))]) f[now][dl[t+(x<<(p-))]]+=f[la][k];
}
}
else if(!p)
{
if(ma[i][j]!=)
{
if(j!=m&&ma[i][j]==&&dl[t+(y<<(q-))]) f[now][dl[t+(y<<(q-))]]+=f[la][k];
if(i!=n&&dl[t+(x<<(q-))]) f[now][dl[t+(x<<(q-))]]+=f[la][k];
}
}
else if(p==&&q==)
{
if(!t&&i==nn&&j==mm) ans+=f[la][k];
}
else if(p==&&q==)
{
if(ma[i][j]==)
{
if(dl[t]) f[now][dl[t]]+=f[la][k];
}
}
else if(p==&&q==)
{
if(ma[i][j]==)
{
int u,tmp;
for(u=j+,tmp=;u<=m&&tmp>=;tmp+=(b[t/xp[u]]==)-(b[t/xp[u]]==),u++);
u--;
if(t-xp[u]<) continue;
if(dl[t-xp[u]]) f[now][dl[t-xp[u]]]+=f[la][k];
}
}
else if(p==&&q==)
{
if(ma[i][j]==)
{
int u,tmp;
for(u=j-,tmp=;u>&&tmp>=;tmp+=(b[t/xp[u]]==)-(b[t/xp[u]]==),u--);
u++;
if(dl[t+xp[u]]) f[now][dl[t+xp[u]]]+=f[la][k];
}
}
}
else
{
if(!p&&!q&&dl[t]) f[now][dl[t]]+=f[la][k];
}
}
}
for(int j=zz;j>=;j--)
{
if(b[tot[j]]==)
{
if(dl[tot[j]/]) f[now][j]=f[now][dl[tot[j]/]];
else f[now][j]=;
}
else f[now][j]=;
}
}
printf("%lld\n",ans);
return ;
}

bzoj3125: CITY 题解的更多相关文章

  1. ZOJ 3195 Design the city 题解

    这个题目大意是: 有N个城市,编号为0~N-1,给定N-1条无向带权边,Q个询问,每个询问求三个城市连起来的最小权值. 多组数据 每组数据  1 < N < 50000  1 < Q ...

  2. 2019.01.24 bzoj3125: CITY(轮廓线dp)

    传送门 题意简述:给一个n∗mn*mn∗m的网格图,有的格子不能走,有的格子只能竖着走,有的格子只能横着走,问用一条回路覆盖所有能走的格子的方案数. 思路: 就是简单的轮廓线dpdpdp加了一点限制而 ...

  3. caioj1497&&bzoj3125: CITY

    震惊!bzoj居然又被苏大佬D飞了... 这题煞笔模板题好吧. 然而bzojAC caiojWA%40??? 好强啊 今天早上发现是m打成n了囧 #include<cstdio> #inc ...

  4. CodeForces 821D Okabe and City

    Okabe and City 题解: 将行和列也视为一个点. 然后从普通的点走到行/列的点的话,就代表这行/列已经被点亮了. 然后将费用为0的点建上边. 注意讨论(n,m)非亮的情况下. 代码: #i ...

  5. cf公式专场-续

    Benches Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Statu ...

  6. USACO 5.4 Canada Tour

    Canada Tour You have won a contest sponsored by an airline. The prize is a ticket to travel around C ...

  7. 插头dp题表

    bzoj1814: Ural 1519 Formula 1 bzoj3125: CITY bzoj1210: [HNOI2004]邮递员 bzoj2331: [SCOI2011]地板 bzoj1187 ...

  8. Codeforces Round #678 (Div. 2)【ABCD】

    比赛链接:https://codeforces.com/contest/1436 A. Reorder 题解 模拟一下这个二重循环发现每个位置数最终都只加了一次. 代码 #include <bi ...

  9. 【bzoj3125】CITY 插头dp

    题目描述 给出一个n*m的矩阵,某些格子不能通过,某些格子只能上下通过或左右通过.求经过所有非不能通过格子的哈密顿回路条数. 输入 第一行有两个数N, M表示地图被分割成N*M个块,接下来有N行,每行 ...

随机推荐

  1. .NET 图片像素比较

    /// <summary> /// 图像比较.用于找出两副图片之间的差异位置 /// </summary> public class ImageComparer { /// & ...

  2. LINUX 蓝牙耳机的配置方法

    由于经常使用SKYPE聊天打电话,一直觉得被拴在电脑前面不是很自由,终于在一个周末,一激动买了一个蓝牙耳机.经过几天的努力在Linux/Debian上用了起来,现在就把这个配置过程和大家分享. 第一 ...

  3. Android 查看Apk签名方式V1和V2

    Android 查看Apk签名方式V1和V2 java -jar apksigner.jar verify -v my.apk -- Verifies Verified using v1 scheme ...

  4. Win8Metro(C#)数字图像处理--2.30直方图均衡化

    原文:Win8Metro(C#)数字图像处理--2.30直方图均衡化 [函数名称] 直方图均衡化函数HistogramEqualProcess(WriteableBitmap src) [算法说明] ...

  5. textblock的LineHeight的调整

    原文:textblock的LineHeight的调整 <TextBlock Width="113.594" Height="73.667" Text=&q ...

  6. cairo 图形库

    简介 提到cairo,估计很少知道这还是一个图形库的名字(http://cairographics.org),Linux的两大流行桌面环境KDE和Gnome,其对应的基础组件是QT和GTK+,相对于框 ...

  7. 《解读window核心编程》 之 进程

    1.         进程是执行文件的运行时形态.包括两部分:内核数据(对应内核对象).地址空间(包括执行文件代码和栈堆等动态内存). 2.         把VC的“系统-子系统”值删除掉,即不指定 ...

  8. ring3层一种占用文件的方法(DuplicateHandle以后,把占用文件的句柄丢给系统进程,导致被占用)

    前段时间,一个测试工程师问我关于怎样长时间的占用一个文件,而使别的程序无法再访问这个文件,想起以前很多病毒木马经常劫持hosts文件不放,除非你找到占用文件的程序,并强行结束掉,否则怎么也访问不了ho ...

  9. 你所忽略的,覆盖equals时需要注意的事项《effective java》

    我们都知道Object的equals的比较其实就是==的比较,其实是内存中的存放地址的比较.正常逻辑上:类的每个实例本质上都是唯一的. 在工作中我们实际的业务逻辑往往有可能出现一些相对特殊的需求需要对 ...

  10. 【前端工具】页面加载获取url param

    例如跳转进入一个页面: https://mp.csdn.net/postedit/74766644?name=catalina&flag=1 函数: function getParam(par ...