Description

A square township has been divided up into n*m(n rows and m columns) square plots (1<=N,M<=8),some of them are blocked, others are unblocked. The Farm is located in the lower left plot and the Market is located in the lower right plot. Tony takes her tour of the township going from Farm to Market by walking through every unblocked plot exactly once. 
Write a program that will count how many unique tours Betsy can take in going from Farm to Market. 

Input

The input contains several test cases. The first line of each test case contain two integer numbers n,m, denoting the number of rows and columns of the farm. The following n lines each contains m characters, describe the farm. A '#' means a blocked square, a '.' means a unblocked square. 
The last test case is followed by two zeros. 

Output

For each test case output the answer on a single line.
 
题目大意:找到一条路径,经过所有非阻塞点,从右下到达左下。
思路:在最后加两排
.#######.
.......
 
代码(16MS):
 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL; const int MAXN = ;
const int SIZEH = ;
const int MAXH = ; struct hash_map {
int head[SIZEH], size;
int state[MAXH], next[MAXH];
LL val[MAXH]; void init() {
memset(head, -, sizeof(head));
size = ;
} void insert(int st, LL sv) {
int h = st % SIZEH;
for(int p = head[h]; ~p; p = next[p]) {
if(state[p] == st) {
val[p] += sv;
return ;
}
}
state[size] = st; val[size] = sv; next[size] = head[h]; head[h] = size++;
}
} hashmap[]; hash_map *cur, *last;
int acc[] = {, -, , };
char mat[MAXN][MAXN];
int n, m, en, em; int getB(int state, int i) {
return (state >> (i << )) & ;
} void setB(int &state, int i, int val) {
state = (state & ~( << (i << ))) | (val << (i << ));
} int getLB(int state, int i) {
int ret = i, cnt = ;
while(cnt) {
--ret;
cnt += acc[getB(state, ret)];
}
return ret;
} int getRB(int state, int i) {
int ret = i, cnt = -;
while(cnt) {
++ret;
cnt += acc[getB(state, ret)];
}
return ret;
} 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->val[k]);
swap(cur, last);
}
}
for(int k = ; k < last->size; ++k)
if(last->state[k] == ) return last->val[k];
return ;
} int main() {
while(scanf("%d%d", &n, &m) != EOF) {
if(n == && m == ) break;
memset(mat, , sizeof(mat));
for(int i = ; i < n; ++i) scanf("%s", mat[i]);
for(int i = ; i < m - ; ++i) mat[n][i] = '#';
n += ;
cout<<solve()<<endl;
}
}

POJ 1739 Tony's Tour(插头DP)的更多相关文章

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

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

  2. [POJ 1739] Tony's Tour

    Link: POJ 1739 传送门 Solution: 这题除了一开始的预处理,基本上就是插头$dp$的模板题了 由于插头$dp$求的是$Hamilton$回路,而此题有起点和终点的限制 于是可以构 ...

  3. POJ 1739 Tony's Tour (DP)

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

  4. POJ 2411 Mondriaan's Dream 插头dp

    题目链接: http://poj.org/problem?id=2411 Mondriaan's Dream Time Limit: 3000MSMemory Limit: 65536K 问题描述 S ...

  5. POJ 3133 Manhattan Wiring (插头DP,轮廓线,经典)

    题意:给一个n*m的矩阵,每个格子中有1个数,可能是0或2或3,出现2的格子数为2个,出现3的格子数为2个,要求将两个2相连,两个3相连,求不交叉的最短路(起终点只算0.5长,其他算1). 思路: 这 ...

  6. 【POJ】1739 Tony's Tour

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

  7. 插头DP专题

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

  8. 插头DP题目泛做(为了对应WYD的课件)

    题目1:BZOJ 1814 URAL 1519 Formula 1 题目大意:给定一个N*M的棋盘,上面有障碍格子.求一个经过所有非障碍格子形成的回路的数量. 插头DP入门题.记录连通分量. #inc ...

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

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

随机推荐

  1. 搭建Extjs框架(二)

    搭建Extjs 框架 二.编写入口文件 app.js,配置extjs 组件\视图文件路径 并将app.js引入index.html       在app.js中指定一些文件的路径,Extjs页面的起始 ...

  2. Python Monitoring UPS with SNMPWALK

    ##Background My co-worker told me he needed to monitor UPS with SNMP module but he only can get hexa ...

  3. PHP中如何对二维数组按某个键值进行排序

    $arr=[     array(         'name'=>'张三',         'age'=>28     ),     array(         'name'=> ...

  4. hadoop生态搭建(3节点)-16.elk配置

    # ==================================================================ELK环境准备 # 修改文件限制 # * 代表Linux所有用户 ...

  5. 从零开始一个http服务器(三)-返回response 构造

    从零开始一个http服务器(三) 代码地址 : https://github.com/flamedancer/cserver git checkout step3 运行: gcc request.h ...

  6. 基于傅里叶变换的音频重采样算法 (附完整c代码)

    前面有提到音频采样算法: WebRTC 音频采样算法 附完整C++示例代码 简洁明了的插值音频重采样算法例子 (附完整C代码) 近段时间有不少朋友给我写过邮件,说了一些他们使用的情况和问题. 坦白讲, ...

  7. C指针(3)——指向指针的指针(程序讲解)

    int **q可以分成两部分,即int* 和 (*q),后面的 “q” 中的* 表示q是一个指针变量,前面的int*表示指针变量q只能存放int*型变量的地址.int** q表示为指针变量q只能存放i ...

  8. BAPC 2014 Preliminary

    // 题目链接: https://nanti.jisuanke.com/t/282041 //动态规划,重复利用子问题的最优,来求解当前最优问题 #include <iostream> # ...

  9. Hibernate学习笔记三

    1.1.1 Hibernate的关联关系映射:(多对多) 1.1.1.1 多对多的配置: 步骤一创建实体和映射: Student: public class Student { private Int ...

  10. window下创建虚拟环境

    一. windows下创建虚拟环境 1. 终端下执行命令:python -m pip install -upgrade pip 2. pip install virtualenv 3. 在本地创建一个 ...