题目描述

给出一个n*m的矩阵,某些格子不能通过,某些格子只能上下通过或左右通过。求经过所有非不能通过格子的哈密顿回路条数。

输入

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

输出

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

样例输入

4 4
....
..-.
....
....

样例输出

1


题解

插头dp

这道题 的唯一差别在于:部分格子只能上下通过或只能左右通过。

因此判断条件那里改一改就好了。

这里学了一下 CQzhangyu 的技♂巧:判断时只需要判断当前状态是否适用于当前格子,以及转移是否适用于当前格子即可。这样不合法的状态就会在下一步剪掉。这一步可以省很大的代码量。

注意开long long(题面的long指的就是int)

#include <cstdio>
#include <cstring>
typedef long long ll;
int m , a[13][13] , b[13] , w[1600000] , v[42000] , tot;
ll f[13][13][42000];
char str[14];
void dfs(int p , int c , int now)
{
if(c < 0 || c > m - p + 1) return;
if(p > m)
{
w[now] = ++tot , v[tot] = now;
return;
}
dfs(p + 1 , c , now);
dfs(p + 1 , c + 1 , now + b[p]);
dfs(p + 1 , c - 1 , now + 2 * b[p]);
}
inline int l(int v , int p)
{
int i , c = 0;
for(i = p ; ~i ; i -- )
{
if(v / b[i] % 3 == 1) c -- ;
if(v / b[i] % 3 == 2) c ++ ;
if(!c) return i;
}
return -1;
}
inline int r(int v , int p)
{
int i , c = 0;
for(i = p ; i <= m ; i ++ )
{
if(v / b[i] % 3 == 1) c ++ ;
if(v / b[i] % 3 == 2) c -- ;
if(!c) return i;
}
return -1;
}
int main()
{
int n , i , j , k , x , y , p , q;
ll ans = 0;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%s" , str + 1);
for(j = 1 ; j <= m ; j ++ )
{
if(str[j] == '.' || str[j] == '-') a[i][j] |= 1;
if(str[j] == '.' || str[j] == '|') a[i][j] |= 2;
if(str[j] != '#') x = i , y = j;
}
}
b[0] = 1;
for(i = 1 ; i <= m ; i ++ ) b[i] = b[i - 1] * 3;
dfs(0 , 0 , 0);
f[0][m][w[0]] = 1;
for(i = 1 ; i <= n ; i ++ )
{
for(j = 1 ; j <= tot ; j ++ )
if(v[j] % 3 == 0)
f[i][0][j] = f[i - 1][m][w[v[j] / 3]];
for(j = 1 ; j <= m ; j ++ )
{
for(k = 1 ; k <= tot ; k ++ )
{
p = v[k] / b[j - 1] % 3 , q = v[k] / b[j] % 3;
if((p && !(a[i][j] & 1)) || (q && !(a[i][j] & 2))) continue;
if(!a[i][j]) f[i][j][k] += f[i][j - 1][k];
else
{
if(!p && !q && a[i][j] == 3) f[i][j][w[v[k] + b[j - 1] + 2 * b[j]]] += f[i][j - 1][k];
if(!p && q && a[i][j] & 1) f[i][j][k] += f[i][j - 1][k];
if(p && !q && a[i][j] & 2) f[i][j][k] += f[i][j - 1][k];
if(!p && q) f[i][j][w[v[k] + q * (b[j - 1] - b[j])]] += f[i][j - 1][k];
if(p && !q) f[i][j][w[v[k] + p * (b[j] - b[j - 1])]] += f[i][j - 1][k];
if(p == 1 && q == 1) f[i][j][w[v[k] - b[j - 1] - b[j] - b[r(v[k] , j)]]] += f[i][j - 1][k];
if(p == 2 && q == 2) f[i][j][w[v[k] - 2 * (b[j - 1] + b[j]) + b[l(v[k] , j - 1)]]] += f[i][j - 1][k];
if(p == 2 && q == 1) f[i][j][w[v[k] - 2 * b[j - 1] - b[j]]] += f[i][j - 1][k];
if(p == 1 && q == 2 && i == x && j == y && v[k] == b[j - 1] + 2 * b[j]) ans += f[i][j - 1][k];
}
}
}
}
printf("%lld\n" , ans);
return 0;
}

【bzoj3125】CITY 插头dp的更多相关文章

  1. HDU 4064 Carcassonne(插头DP)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4064 Problem Description Carcassonne is a tile-based ...

  2. ural1519插头DP

    1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, that V ...

  3. 插头DP学习笔记——从入门到……????

    我们今天来学习插头DP??? BZOJ 2595:[Wc2008]游览计划 Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该 ...

  4. RUAL1519 Formula 1 【插头DP】

    RUAL1519 Formula 1 Background Regardless of the fact, that Vologda could not get rights to hold the ...

  5. URAL 1519 Formula 1(插头DP,入门题)

    Description Background Regardless of the fact, that Vologda could not get rights to hold the Winter ...

  6. URAL1519 Formula 1 —— 插头DP

    题目链接:https://vjudge.net/problem/URAL-1519 1519. Formula 1 Time limit: 1.0 secondMemory limit: 64 MB ...

  7. bzoj3125: CITY 题解

    3125: CITY Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 486  Solved: 213[Submit][Status][Discuss] ...

  8. [专题总结]初探插头dp

    彻彻底底写到自闭的一个专题. 就是大型分类讨论,压行+宏定义很有优势. 常用滚动数组+哈希表+位运算.当然还有轮廓线. Formula 1: 经过所有格子的哈密顿回路数. 每个非障碍点必须有且仅有2个 ...

  9. 「总结」插头$dp$

    集中做完了插头$dp$ 写一下题解. 一开始学的时候还是挺蒙的. 不过后来站在轮廓线$dp$的角度上来看就简单多了. 其实就是一种联通性$dp$,只不过情况比较多而已了. 本来转移方式有两种.逐行和逐 ...

随机推荐

  1. Ubuntu + apache + Mysql +php

    发生了乱码问题: 打开apache配置文件: sudo gedit /etc/apache2/apache2.conf,在最后面加上:AddDefaultCharset UTF-8,如果还乱码,再将U ...

  2. LVS入门篇(二)之LVS基础

    1. LVS介绍 LVS是Linux虚拟服务器(LinuxVirtualServers),使用负载均衡技术将多台服务器组成一个虚拟服务器.它为适应快速增长的网络访问需求提供了一个负载能力易于扩展,而价 ...

  3. Qt 利用XML文档,写一个程序集合 三

    接上一篇https://www.cnblogs.com/DreamDog/p/9214052.html 滚动区域实现, 滚动区域可以三成分层 第一层,显示内容 中间层,滚动层 第三层,爸爸层 把我们要 ...

  4. 韦大仙--LoadRunner压力测试:详细操作流程

    一. 录制脚本 1.安装完毕后,创建脚本: 点击OK之后,会弹出网址,之后创建Action,每进一个页面添加一个Action,录制结束后,终止录制. 二. 修改脚本 1.脚本参数化 将登录的用户名密码 ...

  5. win7下配置spark

    1.安装jdk(配置JAVA_HOME,CLASSPATH,path) 2.安装scala(配置SCALA_HOME,path) 3.安装spark Spark的安装非常简单,直接去Download ...

  6. 常用JDBC数据库驱动包和类名

    MySQL数据库: 1)驱动包:https://mvnrepository.com/artifact/mysql/mysql-connector-java(下载路径) 2)驱动类名:com.mysql ...

  7. Kafka安装之二 在CentOS 7上安装Kafka

    一.简介 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据. 这 ...

  8. CSS中水平居中设置的几种方式

    1.行内元素: 如果被设置元素为文本.图片等行内元素时,水平居中是通过给父元素设置 text-align:center 来实现的. <body> <div class="t ...

  9. MacOS下搭建python环境

    1. 安装须知 Mac OS自身其实已经带有Python,版本为2.7.X,这个Python主要用于支持系统文件和XCode,所以我们在安装新的Python版本时候最好不要影响这部分. 这里就会出现一 ...

  10. 2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest Problem F. Format

    题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229510 时间限制:1s 空间限制:512MB 题目大意: 给定一个字符串,使用%[...] ...