轮廓线 DP
模拟赛中遇到了,被迫花了一天来学习。
轮廓线 DP 本质上是逐格转移的状压 DP,有特别经典的图可以说明:
思想上非常好理解,就是把分界处的状态压缩起来。主要是实现上有许多技巧需要说一下。第一个是状态的表示方法,在大多数情况只需要用 0/1 来代表这个位置是否存在插头即可,一般会以二进制或者四进制的形式压缩成一个整型(
然后是状态是转移方法,一般而言轮廓线 DP 每个阶段存在的合法状态不会特别多,所以可以考虑把合法状态哈希存储,然后在下一个阶段就只需要找出哈希表里所有的元素即可,发现这一部分是可以滚动的,进一步压缩空间(29009
是一把比较顺眼的钥匙)。对于一个状态,要转移到下一个阶段,就只需要提取出这个状态对应的上插头和左插头,然后加上自己的状态进行一大堆分类讨论就可以了。然后结合例题分析,毕竟剩下的东西因题而异。放个我的哈希板子:
struct node{int pl,data,nxt;};
struct Hash{
node data[M];int nowCnt,head[H];
inline void clear(){nowCnt=0;memset(head,0,sizeof(head));}
inline void insert(int pl,int val){
int key=pl%H;
for(int i=head[key];i;i=data[i].nxt)if(data[i].pl==pl)return add(data[i].data,val);
data[++nowCnt]=(node){pl,val,head[key]};head[key]=nowCnt;
}
}h[2];
【模板】插头dp 插头 DP 的板子,由于强制要求只有一条闭合折线,所以需要用到括号表示法。特别的是由于希望覆盖满所有的格子,统计答案是时候只能在最后一个格子统计,并且此时强制上插头和左插头配对(这样才能做到不重不漏)。另外,如果当前格子恰好是两个左括号或者两个右括号时需要调转其中一个配对处的方向(调转上方显然好写,需要写个小小的函数来找到配对位置在哪)。然后就没了。
Eat the Trees 和上一道题很像,只是少了强制一条的限制,这样一来面对两个插头就不需要分类讨论左括号还是右括号了,所以状态的每一位只需要记录一个值即可。然后就不需要哈希了。
神秘的生物 最小表示法的应用,由于希望最后只有一个连通块,所以在上方有插头并且自己不选的时候要特别注意,如果自己不选会导致上插头断掉的话,那么这个状态就会是不合法的(判断上直接找轮廓线上有几个同类插头即可)。一个状态能贡献答案当且仅当轮廓线上只有一种插头(也就是当前只有一个连通块),然后就是要用最小表示法来缩减空间。
神奇游乐园 和板子是很像的,少了一些限制(每个格子不需要都选择,话说有了这个限制谁还搞 DP 啊),所以呢就多了一些决策,贡献答案的地方也就多了一些(要满足当前轮廓线恰好只有一对插头),然后就没什么了。
白金元首与莫斯科 也可以用状压来做。由于骨牌的结构是简单的,所以状态只需要记录一个布尔值即可,这样一来状态就非常稠密了,导致哈希大概率会被卡掉。转移上非常板。统计答案肯定不能每次暴力统计,考虑把这个点扣掉,那么当前点的答案就是从上往下到这个点的部分和从下往上到这个点的部分刚好可以拼起来并且不会延申到这个格子的方案,画图发现这等价于两个状态完全相同并且第
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库