Description

Background

Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well-known, that the city will conduct one of the Formula 1 events. Surely, for such an important thing a new race circuit should be built as well as hotels, restaurants, international airport - everything for Formula 1 fans, who will flood the city soon. But when all the hotels and a half of the restaurants were built, it appeared, that at the site for the future circuit a lot of gophers lived in their holes. Since we like animals very much, ecologists will never allow to build the race circuit over the holes. So now the mayor is sitting sadly in his office and looking at the map of the circuit with all the holes plotted on it.

Problem

Who will be smart enough to draw a plan of the circuit and keep the city from inevitable disgrace? Of course, only true professionals - battle-hardened programmers from the first team of local technical university!.. But our heroes were not looking for easy life and set much more difficult problem: "Certainly, our mayor will be glad, if we find how many ways of building the circuit are there!" - they said.
It should be said, that the circuit in Vologda is going to be rather simple. It will be a rectangle NM cells in size with a single circuit segment built through each cell. Each segment should be parallel to one of rectangle's sides, so only right-angled bends may be on the circuit. At the picture below two samples are given for N = M = 4 (gray squares mean gopher holes, and the bold black line means the race circuit). There are no other ways to build the circuit here.

Input

The first line contains the integer numbers N and M (2 ≤ NM ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.

Output

You should output the desired number of ways. It is guaranteed, that it does not exceed 2 63-1.
 
题目大意:找一个环,经过所有是'.'的点一次,问有多少个这样的哈密尔顿环。
思路:插头DP,参考IOI国家集训队论文,陈丹琦的《基于连通性状态压缩的动态规划问题》
PS:本来想不用hash的,但是写完发现状态根本存不下啊魂淡
 
代码(78MS):(Update:2014年11月14日)
 #include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL; const int MAXH = ;
const int SIZEH = ; struct hash_map {
int head[SIZEH];
int next[MAXH], state[MAXH];
LL value[MAXH];
int size; void init() {
memset(head, -, sizeof(head));
size = ;
} void insert(int st, LL tv) {
int h = st % SIZEH;
for(int i = head[h]; ~i; i = next[i]) {
if(state[i] == st) {
value[i] += tv;
return ;
}
}
value[size] = tv; state[size] = st;
next[size] = head[h]; head[h] = size++;
}
} hashmap[]; hash_map *cur, *last;
int acc[] = {, -, , }; int n, m, en, em;
char mat[][]; int getB(int state, int i) {
i <<= ;
return (state >> i) & ;
} int getLB(int state, int i) {
int ret = i, cnt = ;
while(cnt) cnt += acc[getB(state, --ret)];
return ret;
} int getRB(int state, int i) {
int ret = i, cnt = -;
while(cnt) cnt += acc[getB(state, ++ret)];
return ret;
} void setB(int &state, int i, int tv) {
i <<= ;
state = (state & ~( << i)) | (tv << i);
} void update(int x, int y, int state, LL tv) {
int left = getB(state, y);
int up = getB(state, y + );
if(mat[x][y] == '*') {
if(left == && up == ) cur->insert(state, tv);
return ;
}
if(left == && up == ) {
if(x == n - || y == m - ) return ;
int newState = state;
setB(newState, y, );
setB(newState, y + , );
cur->insert(newState, tv);
} else if(left == || up == ) {
if(x < n - ) {
int newState = state;
setB(newState, y, up + left);
setB(newState, y + , );
cur->insert(newState, tv);
}
if(y < m - ) {
int newState = state;
setB(newState, y, );
setB(newState, y + , up + left);
cur->insert(newState, tv);
}
} else {
int newState = state;
setB(newState, y, );
setB(newState, y + , );
if(left == && up == ) setB(newState, getRB(state, y + ), );
if(left == && up == && !(x == en && y == em)) return ;
if(left == && up == ) setB(newState, getLB(state, y), );
cur->insert(newState, tv);
}
} void findend() {
for(en = n - ; en >= ; --en)
for(em = m - ; em >= ; --em) if(mat[en][em] == '.') return ;
} LL solve() {
findend();
cur = hashmap, last = hashmap + ;
last->init();
last->insert(, );
for(int i = ; i < n; ++i) {
int sz = last->size;
for(int k = ; k < sz; ++k) last->state[k] <<= ;
for(int j = ; j < m; ++j) {
cur->init();
sz = last->size;
for(int k = ; k < sz; ++k)
update(i, j, last->state[k], last->value[k]);
swap(cur, last);
}
}
return last->size ? last->value[] : ;
} int main() {
scanf("%d%d", &n, &m);
for(int i = ; i < n; ++i) scanf("%s", mat[i]);
cout<<solve()<<endl;
}

URAL 1519 Formula 1(插头DP,入门题)的更多相关文章

  1. bzoj1814 Ural 1519 Formula 1(插头dp模板题)

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 924  Solved: 351[Submit][Sta ...

  2. bzoj 1814: Ural 1519 Formula 1 插头dp经典题

    用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. #include<iostream> #include<cstdio> #include<cstr ...

  3. 【BZOJ1814】Ural 1519 Formula 1 插头DP

    [BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...

  4. bzoj 1814 Ural 1519 Formula 1 插头DP

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 942  Solved: 356[Submit][Sta ...

  5. Ural 1519 Formula 1 插头DP

    这是一道经典的插头DP单回路模板题. 用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制. 1.当同时存在左.上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连 ...

  6. bzoj 1814 Ural 1519 Formula 1 ——插头DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1814 普通的插头 DP .但是调了很久.注意如果合并两个 1 的话,不是 “把向右第一个 2 ...

  7. BZOJ1814: Ural 1519 Formula 1(插头Dp)

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

  8. 【Ural】1519. Formula 1 插头DP

    [题目]1519. Formula 1 [题意]给定n*m个方格图,有一些障碍格,求非障碍格的哈密顿回路数量.n,m<=12. [算法]插头DP [题解]<基于连通性状态压缩的动态规划问题 ...

  9. [URAL1519] Formula 1 [插头dp入门]

    题面: 传送门 思路: 插头dp基础教程 先理解一下题意:实际上就是要你求这个棋盘中的哈密顿回路个数,障碍不能走 看到这个数据范围,还有回路处理,就想到使用插头dp来做了 观察一下发现,这道题因为都是 ...

  10. 【BZOJ1814】Ural 1519 Formula 1 (插头dp)

    [BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...

随机推荐

  1. jQuery 常用核心方法

    jQuery 常用核心方法 .each() 遍历一个jQuery对象,为每个匹配元素执行一个函数 $('p').each(function(idx,node){ $(node).text(idx + ...

  2. PHP的发展历程

    PHP的发展历程 了解一门语言,我们必须知道这门语言的发展史,现在我通过版本的变化以时间轴的形式来说明PHP的发展历程. 1.1995年初PHP1.0诞生 Rasmus Lerdof发明了PHP,这是 ...

  3. s3c2440中断控制器操作

    一.ARM中断体系结构 arm有7中异常工作模式 用户模式.快中断模式.管理模式.数据访问终止模式.中断模式.系统模式.未定义指令终止模式. 几种模式有什么不同呢, 1.不同的寄存器 2.不同的权限 ...

  4. 20190129-‘abcdefgh’里面挑出3个字母进行组合,一共有多少组合

    一. 百度面试题‘abcdefgh’里面挑出3个字母进行组合,一共有多少组合,要求3个字母中不能有重复的组合,三个字母同时出现的次数只能出现一次,如出现了abc就不能出现cab,bca等 思路: 1. ...

  5. mac下使用git的冲突的解决方案

    博主之前一直是在windows系统下进行软件代码的开发,window下有很多git的使用工具,如tortoisegit等是个很好的git项目管理工具.而再mac版下的git项目代码管理工具,本人找了好 ...

  6. 环境变量Path简介

    更多详细专业的详解,请参见:http://www.cnblogs.com/sunada2005/articles/2725277.html 什么是Path变量: PATH环境变量.作用是指定命令搜索路 ...

  7. MySql——查看数据库性能基本参数

    使用show status可以查看数据库性能的参数,基本语法:show status like 'value'; 例如: show status like 'Connections';/*连接mysq ...

  8. SpringBoot-04:SpringBoot在idea中的俩种创建方式

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 创建SpringBoot工程有很多种方式,我只讲俩种最为常见的 一,依托springboot官网提供的模板.( ...

  9. 13、Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  10. docker in docker

    docker run --rm可以从一个镜像启动容器,并在容器执行完成后自动删除,这在计算任务中非常有用. 例如,我们通过以下步骤完成计算任务容器的启动: 1 将输入数据通过卷挂载方式连接到计算任务容 ...