题目大意:

找到多条回路覆盖所有非障碍格子,问这样回路的种数

这里的插头与URAL1519 不一样的是 只要管它是否存在即可,只需要1个二进制位表示状态

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std;
#define ll unsigned long long
const int HASH = ;
const int STATE = ;
const int MAXD = ;
int n , m ;
int code[MAXD] , mp[MAXD][MAXD]; struct HASHMAP{
int head[HASH] , next[STATE] , state[STATE] , size;
ll f[STATE]; void init(){
size = ;
memset(head , - , sizeof(head));
} void push_in(int st , ll sum){
int h = st%HASH;
for(int i = head[h] ; ~i ; i=next[i]){
if(st == state[i]){
f[i]+=sum;
return ;
}
}
f[size]=sum;
state[size] = st;
next[size] = head[h];
head[h] = size++;
}
}hashmap[]; void decode(int *code , int m , int st)
{
for(int i=m ; i>= ; i--){
code[i] = st&;
st>>=;
}
} int encode(int *code , int m)
{
int st=;
for(int i= ; i<=m ; i++){
st<<=;
st |= code[i];
}
return st;
} void init()
{
scanf("%d%d" , &n , &m);
for(int i= ; i<=n ; i++){
for(int j= ; j<=m ; j++){
scanf("%d" , &mp[i][j]);
}
}
} void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧
{
for(int i=m ; i>= ; i--) code[i] = code[i-];
code[] = ;
} void dpblank(int i , int j , int cur) //处理可执行格子
{
// cout<<"ok: "<<i<<" "<<j<<endl;
int k , left , up;
for(k= ; k<hashmap[cur].size ; k++){
decode(code , m , hashmap[cur].state[k]);
left = code[j-];
up = code[j];
if(left&&up){ //插头均存在 1 1
code[j-] = code[j] = ;
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
// cout<<i<<" "<<j<<" "<<encode(code , m)<<" "<<hashmap[cur].f[k]<<endl;
}
else if(left || up){ // 1 || 1
if(j<m && mp[i][j+]){
//这里面右插头是可选的,所以不存在换行shift()
code[j-] = , code[j] = ;
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
if(i<n && mp[i+][j]){
code[j-] = , code[j] = ;
if(j == m) shift(code , m);
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
else {
if((j<m && mp[i][j+]) && (i<n && mp[i+][j])){
code[j-] = code[j] = ;
hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
}
}
} void dpblock(int i , int j , int cur)
{
// cout<<"flase: "<<i<<" "<<j<<endl;
int k , left , up;
for(k= ; k<hashmap[cur].size ; k++){
decode(code , m , hashmap[cur].state[k]);
left = code[j-] , up = code[j];
if(j == m) shift(code , m);
if(left+up == ) hashmap[cur^].push_in(encode(code , m) , hashmap[cur].f[k]);
}
} ll solve()
{
ll ans = ;
int cur = ;
hashmap[cur].init();
hashmap[cur].push_in( , );
for(int i= ; i<=n ; i++){
for(int j= ; j<=m ; j++){
hashmap[cur^].init();
if(mp[i][j]) dpblank(i , j , cur);
else dpblock(i , j , cur);
cur ^= ;
}
}
for(int i= ; i<hashmap[cur].size ; i++)
ans += hashmap[cur].f[i];
return ans;
} int main()
{
// freopen("in.txt" , "r" , stdin);
int T , cas=;
scanf("%d" , &T);
while(T--)
{
init();
printf("Case %d: There are %I64u ways to eat the trees.\n" , ++cas , solve());
}
return ;
}

HDU 1693 二进制表示的简单插头dp的更多相关文章

  1. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

  2. HDU 1693 Eat the Trees(插头DP,入门题)

    Problem Description Most of us know that in the game called DotA(Defense of the Ancient), Pudge is a ...

  3. HDU 1693 Eat the Trees (插头DP)

    题意:给一个n*m的矩阵,为1时代表空格子,为0时代表障碍格子,问如果不经过障碍格子,可以画一至多个圆的话,有多少种方案?(n<12,m<12) 思路: 这题不需要用到最小表示法以及括号表 ...

  4. hdu 1693 : Eat the Trees 【插头dp 入门】

    题目链接 题意: 给出一个n*m大小的01矩阵,在其中画线连成封闭图形,其中对每一个值为1的方格,线要恰好穿入穿出共两次,对每一个值为0的方格,所画线不能经过. 参考资料: <基于连通性状态压缩 ...

  5. HDU 1565 方格取数(1) ——插头DP

    [题目分析] 其实直接状压就可以了. 但是有点闲,又写了一个可读性极差,智商低下,很(gou)好(pi)的代码 [代码] #include <cstdio> #include <cs ...

  6. hdu 4405 Aeroplane chess(简单概率dp 求期望)

    Aeroplane chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  7. TopCoder SRM 722 Div1 Problem 600 DominoTiling(简单插头DP)

    题意  给定一个$12*12$的矩阵,每个元素是'.'或'X'.现在要求$1*2$的骨牌铺满整个矩阵, 'X'处不能放置骨牌.求方案数. 这道题其实和 Uva11270 是差不多的,就是加了一些条件. ...

  8. hdu 1693 Eat the Trees——插头DP

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693 第一道插头 DP ! 直接用二进制数表示状态即可. #include<cstdio> # ...

  9. HDU 1693 Eat the Trees(插头DP)

    题目链接 USACO 第6章,第一题是一个插头DP,无奈啊.从头看起,看了好久的陈丹琦的论文,表示木看懂... 大体知道思路之后,还是无法实现代码.. 此题是插头DP最最简单的一个,在一个n*m的棋盘 ...

随机推荐

  1. Android 图片Exif信息相关的获取与修改

    1 Exif是什么 Exif是一种图像文件格式,它的数据存储于JPEG格式是完全相同的,实际上Exif格式就是JPEG格式头插入了 数码照片的信息,包括拍摄的光圈.快门.平衡白.ISO.焦距.日期时间 ...

  2. hiho1091_clicker背包问题

    问题 类似有限背包问题,题目链接:clicker 实现 #include<stdio.h> #include<cmath> #include<iostream> # ...

  3. 任务调度quartz

    http://www.cnblogs.com/cnjava/archive/2013/02/28/2937291.html

  4. WebDriver 在使用 CSS Selector 与 XPath 在查找元素时如何取舍

    开发在做Web系统时,用的是css div划分层,使用jQuery 选取元素.

  5. VC++编译libpng

    目录 第1章简介    1 第2章 Visual C++6.0    2 2.1 打开项目    2 2.2 编译宏    3 2.2.1 小结    5 第3章 Visual C++2010     ...

  6. 【hdu2196】Computer

    hdu 2196 computer 题意 给你一棵树,边有权值. 对于每一个点,求其与其距离最远的点的距离. 分析 思路1:树的直径 利用直径的性质进行求解,网上资料很多,这里不赘述. #includ ...

  7. 《Java程序设计》第二周学习总结

    20145224陈颢文<Java程序设计>第二周学习总结 教材学习内容总结 一.类型.变量与运算符 1.类型 整数: 可细分为为short整数(占2字节),int整数(占4字节),long ...

  8. Linux GDB常用命令一栏

    Linux GDB 常用命令如下: 1.启动和退出gdb (1)启动:gdb ***:显示一段版权说明: (*** 表示可执行程序名) (2)退出:quit.有的时候输入quit后会出现相关提示:类似 ...

  9. hdu 1805Expressions(二叉树构造的后缀表达式)

    Expressions Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  10. Path Sum [LeetCode]

    Problem Description: http://oj.leetcode.com/problems/path-sum/ Pretty easy. /** * Definition for bin ...