题意:有一个n*8的蜂房(6边形的格子),其中部分是障碍格子,其他是有蜂蜜的格子,每次必须走1个圈取走其中的蜂蜜,在每个格子只走1次,且所有蜂蜜必须取走,有多少种取法?

  

思路:

  以前涉及的只是n*m的矩阵,也就是四边形的,现在变成了6边形,那么每个格子也就有6个方向可以出/进。为了方便考虑,将蜂房变成按列来扫,那么轮廓线需要2*n+1个插头信息。这里不需要用到括号表示法或者最小表示法,只需要表示该位置是否有线即可,所以每个插头仅需1个位就可以表示了。

  转置一下后的蜂房应该是这样的:

  

  轮廓线是一个左,一个左上,一个右上来组成的。当前格子为奇数行时,状态需要左移2位,因为有两个方向(左,左上)是空出来的。其他的只需要根据奇偶数行来判断即可。

2700ms+

 #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=;
int g[N][N], cur, n, m;
struct Hash_Map
{
static const int mod=;
static const int NN=; //至少50万
int head[mod]; //桶指针
int next[NN]; //记录链的信息
LL status[NN]; //状态
LL value[NN]; //状态对应的DP值。
int size; void clear() //清除哈希表中的状态
{
memset(head, -, sizeof(head));
size = ;
} void insert(LL st, LL val) //插入状态st的值为val
{
int h = st%mod;
for(int i=head[h]; i!=-; i=next[i])
{
if(status[i] == st) //这个状态已经存在,累加进去。
{
value[i] += val;
return ;
}
} status[size]= st; //找不到状态st,则插入st。
value[size] = val;
next[size] = head[h] ; //新插入的元素在队头
head[h] = size++;
}
}hashmap[];
inline int getbit(LL s,int pos)
{
return ((s>>pos)&);
} inline LL setbit(LL s,int pos,int bit)
{
s&=~((LL)<<pos);
return (s|(LL)bit<<pos);
} void DP(int i,int j)
{
for(int k=; k<hashmap[cur^].size; k++)
{
LL s=hashmap[cur^].status[k];
LL v=hashmap[cur^].value[k];
int R=getbit(s,*j), DL=getbit(s,*j+), DR=getbit(s,*j+);
LL t=(setbit(s,*j+,)&setbit(s,*j+,)&setbit(s,*j+,));
if(g[i][j]==) //必走格子
{
if( R && DL && DR ) continue; //3个插头,冲突了。
if( R && DL || R && DR || DL && DR ) hashmap[cur].insert(t,v); //合并
else if( R || DL || DR ) //延续
{
if( j+<m ) hashmap[cur].insert(setbit(t,*j+,), v); //右
if( i+<n )
{
if( !(i&) || j+<m ) hashmap[cur].insert(setbit(t,*j+,), v); //右下
if( (i&) || j> ) hashmap[cur].insert(setbit(t,*j+,), v); //左下
}
}
else //新插头
{
if(i+<n)
{
if( (j>&&!(i&)) || (j+<m&&(i&)) ) //(左下,右下)
hashmap[cur].insert( setbit(s,*j+,)|setbit(s,*j+,), v);
if( j+<m )
{
if( (i&) || j> ) //(左下,右)
hashmap[cur].insert( setbit(s,*j+,)|setbit(s,*j+,), v);
if( !(i&) || j+<m ) //(右下,右)
hashmap[cur].insert( setbit(s,*j+,)|setbit(s,*j+,), v);
}
}
}
}
else if(R+DL+DR==) hashmap[cur].insert(s,v); //障碍格子
}
} void cal()
{
cur=;
hashmap[cur].clear();
hashmap[cur].insert(,);
for(int i=; i<n; i++)
{
if( !(i&) ) //只有奇数行才需要左移
{
for(int k=; k<hashmap[cur].size; k++) hashmap[cur].status[k]<<=;
}
for(int j=; j<m; j++)
{
cur^=;
hashmap[cur].clear();
DP(i,j);
}
}
}
LL print()
{
for(int i=; i<hashmap[cur].size; i++)
if(hashmap[cur].status[i]==)
return hashmap[cur].value[i];
return ;
} int main()
{
freopen("input.txt", "r", stdin);
while(~scanf("%d%d",&n,&m))
{
memset(g, , sizeof(g));
char c1,c2;
for(int i=; i<m; i++)
{
c1=getchar();
while(!isalpha(c1)) c1=getchar();
c2=getchar();
while(!isalpha(c2)) c2=getchar();
g[c2-'A'][c1-'A']=; //1为障碍格子
}
m=;
swap(n,m);
for(int i=; i*<n; i++)
{
for(int j=; j<m; j++)
swap(g[i][j],g[n--i][j]);
} cal();
printf("%lld\n", print() );
}
return ;
}

AC代码

ZOJ 3466 The Hive II (插头DP,变形)的更多相关文章

  1. ZOj 3466 The Hive II

    There is a hive in the village. Like this. There are 8 columns(from A to H) in this hive. Different ...

  2. 插头DP专题

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

  3. ZOJ 3256 Tour in the Castle 插头DP 矩阵乘法

    题解 这题是一道非常好的插头题,与一般的按格转移的题目不同,由于m很大,要矩阵乘法,这题需要你做一个按列转移的插头DP. 按列转移多少与按格转移不同,但大体上还是基于连通性进行转移.每一列只有右插头是 ...

  4. HDU 3377 Plan (插头DP,变形)

    题意:有一个n*m的矩阵,每个格子中有一个值(可能负值),要从左上角走到右下角,求路径的最大花费. 思路: 除了起点和终点外,其他的点可以走,也可以不走. (2)我用的是括号表示法,所以起始状态为') ...

  5. Ural 1519. Formula 1 优美的插头DP

    今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的, ...

  6. [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样 ...

  7. 【HDU】1693:Eat the Trees【插头DP】

    Eat the Trees Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  8. 插头dp练习

    最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...

  9. 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 ...

随机推荐

  1. 1.11-1.12 Sqoop导入数据时两种增量方式导入及direct

    一.增量数据的导入 1.两种方式 ## query 有一个唯一标识符,通常这个表都有一个字段,类似于插入时间createtime where createtime => 201509240000 ...

  2. Flutter实战视频-移动电商-63.购物车_详细页显示购物车商品数量

    63.购物车_详细页显示购物车商品数量 购物车的图标嵌套在statck组件里面 外层套了一个stack组件 数量我们需要用Provide 返回一个container来做样式 气泡效果,中间是个数字外面 ...

  3. 宝塔Linux 8888 进不去

    一.前言 导致该问题的原因是 Python 版本问题,可能是您更新了 python 的问题.参考宝塔问题的解决方案做的小结.仅供自己做笔记,不作其他用途. 二.解决方案 1.进入shell 命令行,输 ...

  4. __str__,__repr__

    目录 __str__ __repr__ __str__ 打印时触发 class Foo: pass obj = Foo() print(obj) <__main__.Foo object at ...

  5. 调用Web API将文件上传到服务器的方法(.Net Core)

    最近遇到一个将Excel通过Web API存到服务器的问题,其中涉及到Excel的读取.调用API.Web  API怎么进行接收. 一. Excel的读取.调用API Excel读取以及调用API的代 ...

  6. IOS开发 UITabBarController

    UITabBarController使用详解 UITabBarController是IOS中很常用的一个viewController,例如系统的闹钟程 序,ipod程序等.UITabBarContro ...

  7. github的上传本地文档

    自从使用github以来,一直都是在github网站在线上传文件到仓库中,但是有时因为网络或者电脑的原因上传失败.最重要的原因是我习惯本地编辑,完成以后再一起上传github.看过了几个教程,总结出最 ...

  8. Validation(1)

    站在巨人的肩膀上 Java Bean Validation 最佳实践 参数校验是我们程序开发中必不可少的过程.用户在前端页面上填写表单时,前端js程序会校验参数的合法性,当数据到了后端,为了防止恶意操 ...

  9. iOS 利用模态视图实现带黑色蒙版的底部弹窗

    本demo仅适用于iOS8及以上系统. 本文将使用autolayout+storyboard来实现弹窗 第一步.storyboard创建界面 1.打开storyboard 拖一个UIViewcontr ...

  10. JDBC连接池一 自定义连接池

    package com.mozq.jdbc; import java.io.IOException; import java.io.InputStream; import java.sql.Conne ...