ZOJ 3466 The Hive II (插头DP,变形)
题意:有一个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,变形)的更多相关文章
- 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 ...
- 插头DP专题
建议入门的人先看cd琦的<基于连通性状态压缩的动态规划问题>.事半功倍. 插头DP其实是比较久以前听说的一个东西,当初是水了几道水题,最近打算温习一下,顺便看下能否入门之类. 插头DP建议 ...
- ZOJ 3256 Tour in the Castle 插头DP 矩阵乘法
题解 这题是一道非常好的插头题,与一般的按格转移的题目不同,由于m很大,要矩阵乘法,这题需要你做一个按列转移的插头DP. 按列转移多少与按格转移不同,但大体上还是基于连通性进行转移.每一列只有右插头是 ...
- HDU 3377 Plan (插头DP,变形)
题意:有一个n*m的矩阵,每个格子中有一个值(可能负值),要从左上角走到右下角,求路径的最大花费. 思路: 除了起点和终点外,其他的点可以走,也可以不走. (2)我用的是括号表示法,所以起始状态为') ...
- Ural 1519. Formula 1 优美的插头DP
今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的, ...
- [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)
转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样 ...
- 【HDU】1693:Eat the Trees【插头DP】
Eat the Trees Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- 插头dp练习
最近学了插头dp,准备陆续更新插头dp类练习. 学习论文还是cdq那篇<基于连通性状态压缩的动态规划问题>. 基本的想法都讲得很通透了,接下来就靠自己yy了. 还有感谢kuangbin大大 ...
- 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 ...
随机推荐
- 从使用os.system)在python命令(重定向标准输入输出
从使用os.system)在python命令(重定向标准输入输出 python 标准输出stdout stdio os.system通常我可以通过改变sys.stdout的值在python更改标准输出 ...
- java一些jar包的bug(不定期更新)
c3p0-0.9.5.jar 连接池jar包,常用于web项目,关闭连接池时,没有注销所有的driver 解决:可声明一个ServletContextListener的子类并设置监听,重写contex ...
- 3 pyspark学习---sparkContext概述
1 Tutorial Spark本身是由scala语言编写,为了支持py对spark的支持呢就出现了pyspark.它依然可以通过导入Py4j进行RDDS等操作. 2 sparkContext (1) ...
- 「一入 Java 深似海 」系列课程 - 第一期
10分30秒开始 小马哥技术博客: https://mercyblitz.github.io/ github地址: https://github.com/mercyblitz 33分28 https: ...
- 使用JavaScript选择GridView行的方法汇总
一行: e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this.gvUsers, &q ...
- Weekly Contest 78-------->809. Expressive Words (stack)
Sometimes people repeat letters to represent extra feeling, such as "hello" -> "he ...
- Unity3d 3d角色换装实现原理及步骤
http://www.cnblogs.com/dosomething/archive/2012/04/15/2450526.html 1.角色模型制作 unity3d支持Skin动画 但是不支持Ph ...
- IDEA快捷的添加包名
Intellij IDEA使用(十四)—— 在IDEA中创建包(package)的问题 2018年02月24日 17:24:49 _云卷云舒_ 阅读数:6264 标签: intellij idea 更 ...
- JQuery获取iframe中window对象的方法-contentWindow
document.getElementsByTagName('iframe')[0].contentWindow 获取到的就是iframe中的window对象.
- 10M光纤与下载速度KB/s、MB/s的换算
我们经常听说谁开的宽带是4M或10M或20M等等.那这和我们所说的网速“多少MB/s”.“多少KB/s”等同吗? 其实这不是一个概念. 在宽带运营商那里开的宽带,比如4M,其实是说4M bit/s,即 ...