题目描述

给出一个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. 20145209刘一阳《网络对抗》Exp8 Web基础

    20145209刘一阳<网络对抗>Exp8 Web基础 基础问题回答 1.什么是表单? 表单是一个包含表单元素的区域,表单元素是允许用户在表单中(比如:文本域.下拉列表.单选框.复选框等等 ...

  2. cogs1439 货车运输

    cogs1439 货车运输 一道傻逼板子题. 边一定在最大生成树上,这个可以用消圈证明 然后kruskal跑一遍再搜一遍再建ST表再跑LCA这题就做完了. RT PS.交上去的代码把Kruskal打成 ...

  3. uvaoj 156Ananagrams(map和vector组合使用)

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  4. 记录阿里云ECS(Centos7.4)安装mysql 8.0.X服务

    #*.rpm介绍 大多数二进制rpm包都包含在名称中倒数第二个字段中编译rpm的体系结构..rpm软件包有那么几种 *.src.rpm 源程序包,要先通过编译才能安装 *.noarch.rpm 该包适 ...

  5. datax 执行流程分析

    https://www.jianshu.com/nb/29319571 https://www.jianshu.com/p/b10fbdee7e56

  6. NO.02---聊聊Vue提升

    如果本篇有看不明白的地方,请翻阅上一篇文章 上一篇我们讲了如何通过一些简单的动作来改变 store.js 中的数据对象,在实际工作中,这是完全无法满足工作需求的,所以这篇我们来说说如何做一些简单的流程 ...

  7. 技本功丨用短平快的方式告诉你:Flink-SQL的扩展实现

    2019年1月28日,阿里云宣布开源“计算王牌”实时计算平台Blink回馈给ApacheFlink社区.官方称,计算延迟已经降到毫秒级,也就是你在浏览网页的时候,眨了一下眼睛,淘宝.天猫处理的信息已经 ...

  8. MSCOCO - pycocoDemo 学习版

    Reference: https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocoDemo.ipynb https://git ...

  9. hbase中balance机制

    HBase是一种支持自动负载均衡的分布式KV数据库,在开启balance的开关(balance_switch)后,HBase的HMaster进程会自动根据指定策略挑选出一些Region,并将这些Reg ...

  10. Junit4 单元测试框架的常用方法介绍

    Junit 介绍: Junit是一套框架(用于JAVA语言),由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework),即 ...