插头DP 学习笔记

(供复习使用)
插头,其实就是一条线的端点
特别的,左边对应左插头,右边对应右插头
插头DP其实就是一类状压
\(1\) 代表该位置为左插头
\(2\) 代表为右插头
\(0\) 表示无插头
图就不画了,很多题解都画得很好,
这里只解释一下转移
(此时枚举的状态为 zt 方案数为 val b1 为台阶的侧边 b2 为台阶的上端)

if(!mp[i][j]) { if(!b1&&!b2) { ins(zt,val); } }

如果该点不能放点,左上为零才合法

if(!b1&&!b2) { if(mp[i+1][j]&&mp[i][j+1]) { ins(zt+bin[j-1]+2*bin[j],val); } }

如果左上为零,那只有联通右下才合法

f(!b1&&b2) {
    if(mp[i][j+1]) ins(zt,val);
    if(mp[i+1][j]) ins(zt+b2*bin[j-1]-b2*bin[j],val);
} 
if(b1&&!b2) {
    if(mp[i][j+1]) ins(zt+b1*bin[j]-b1*bin[j-1],val);
    if(mp[i+1][j]) ins(zt,val);
}

如果只有左零或上零,考虑另一端端的连接方向即可

if(b1==1&&b2==1) {
    int kl=1;
    for(re int t=j+1;t<=m;t++) {
	if((zt>>(t*2))%4==1) kl++;
	if((zt>>(t*2))%4==2) kl--;
	if(!kl) { ins(zt-bin[j]-bin[j-1]-bin[t],val); break; }
    }
}
if(b1==2&&b2==2) {
    int kl=1;
    for(re int t=j-2;t>=0;t--) {
	if((zt>>(t*2))%4==1) kl--;
	if((zt>>(t*2))%4==2) kl++;
	if(!kl) { ins(zt-2*bin[j]-2*bin[j-1]+bin[t],val); break; }
    }
}

如果左上相等,连接变值即可

if(b1==2&&b2==1) ins(zt-2*bin[j-1]-bin[j],val);
if(i==e1&&j==e2) ans+=val;

两种连值,其中 \(e1\) 和 \(e2\) 为最后枚举到的可放点

上一篇:东方财富炒股公式


下一篇:禅道忘记密码怎么办?