题意:有一个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. mfc给对话框添加背景

    void CMyProjetDlg::OnPaint() { CPaintDC dc(this);//用于绘制设备的上下文 CRect rect; GetClientRect(&rect); ...

  2. 重载和const形参的学习心得

    在C++ primer 5th中,第6章的练习6.39(a)中,关于重载和const形参的学习心得. 练习6.39:说明在下面的每组声明中第二条声明语句是何含义.如果有非法的声明,请指出来. (a)  ...

  3. 2.3 Hive的数据类型讲解及实际项目中如何使用python脚本对数据进行ETL

    一.hive Data Types https://cwiki. apache. org/confluence/display/HiveLanguageManual+Types Numeric Typ ...

  4. outlook2013 解决附件大小限制

    1.先关闭outlook,然后点击"运行"-->输入"regedit" #打开注册表 2.依次打开  “HKEY_CURRENT_USER\Softwar ...

  5. c++函数模板二栈实现

    1 没有使用模板的栈实现 #include <iostream> #include <string> using namespace std; class Stack { pu ...

  6. 5-1 变量与常量 & 6-1课程总结

    变量与常量 常量就是变量定义的的前面加上final final关键字定义常量 新建类FinalDemo 更新常量n的值会报错.常量不可以被修改 常量有个命名规则 一般以大写字母去表示 final in ...

  7. CSS3:nth-child()伪类选择器,Table表格奇偶数行定义样式

    转自爱设计 原文链接http://www.dangshopex.com/jishufenxiang/WEBkaifajishu/8653.html CSS3的强大,让人惊叹,人们在惊喜之余,又不得不为 ...

  8. 洛谷 - P1829 - Crash的数字表格 - 莫比乌斯反演

    求: \(S(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}lcm(i,j)\) 显然: \(S(n,m)=\sum\limits_{i=1}^{n}\ ...

  9. IETester for IE11, IE10, IE9, IE8, IE7 IE 6 and IE5.5 on Windows 8 desktop, Windows 7, Vista and XP

    简介: IETester是一个免费的(用于个人和专业用途)WebBrowser,允许您在Windows 8桌面,Windows 7,Vista和XP上拥有IE11,IE10,IE9,IE8,IE7 I ...

  10. 阿里云物联网 .NET Core 客户端 | CZGL.AliIoTClient:8. 委托事件

    文档目录: 说明 1. 连接阿里云物联网 2. IoT 客户端 3. 订阅Topic与响应Topic 4. 设备上报属性 4.1 上报位置信息 5. 设置设备属性 6. 设备事件上报 7. 服务调用 ...