AT695 マス目

本题选自 DP 优化方法大杂烩 状压部分。

这个题很 nb。下文记 \(n=H\),\(m=W\)。

对于每一列,如果只记录一个格子是否为黑色,那么发现它无法处理从右边绕到左边再绕回去的路径,GG。

改变一下思路,注意到一列最多会产生三个连通块,那么我们用一个长度为 \(n\) 的四进制数表示联通状态。某一位为 \(0\) 表示白格子,为 \(1\) 表示能和 \((1,1)\) 联通,为 \(2\) 表示在某个不与 \((1,1)\) 联通的联通块中,为 \(3\) 表示在某个不与 \((1,1)\) 和状态 \(2\) 所表示的联通块联通的连通块中。一个状态合法,当且仅当两个相邻的不为 \(0\) 的位相同且至少存在一位为 \(1\) 。再观察到连通块 \(2,3\) 其实是等价的,即它们之间无序,所以钦定如果出现了 \(3\),那么在其之前的某一位一定出现了 \(2\)。转移时 \(2^n\) 枚举下一列的黑白状态,用并查集维护连通性,再更新出下一列表示联通状态的四进制数,判断是否合法并转移即可,时间复杂度 \(m8^n\)。最终答案即为 \(f_{n,c}\),其中 \(c\) 为所有合法且第 \(n\) 位为 \(1\) 的四进制数。

在上述限制下,其实满足条件的状态很少。暴力枚举可知 \(n=6\) 时一列合法的状态总数只有 \(S_6=196\),所以我们可以将其离散化。这样时间复杂度被优化到 \(mS_n2^n\log n\),其中 \(\log\) 是并查集的复杂度(其实基本上可以忽略不计了)。

注意到对于一个合法的联通状态,它根据下一列的黑白状态所能转移到的联通状态是固定的,即不随列数的变化而改变,因此可以 \(S_n2^n\log n\) 预处理出来每个联通状态在知道下一列的黑白状态时所转移到的下一列联通状态,时间复杂度被再一次优化到 \(mS_n2^n\),其中 \(S_n\) 只有不到 \(200\),是一个非常优秀的算法,同时也拿到了本题的最优解(2021.7.9)。

理论上本题的 \(m\) 可以出到 \(10^9\) 级别,因为矩阵快速幂可以做到 \(S_n^3\log m\)。

#include <bits/stdc++.h>
using namespace std; #define ll long long
#define mem(x,v) memset(x,v,sizeof(x))
#define mcpy(x,y) memcpy(x,y,sizeof(y)) const int N=200;
const int mod=1e9+7; int n,m,cnt,ans,t[N],g[N],tr[N][64],ed[N];
int c[6],buc[4],f[12],mp[4096]; void add(int &x,int y){x=(x+y)%mod;}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void merge(int u,int v){
u=find(u),v=find(v);
if(u!=v)f[v]=u;
} int main(){
cin>>n>>m;
for(int i=1;i<1<<(2*n);i++,mem(buc,0)){
for(int j=0;j<n;j++)c[j]=i>>(j*2)&3,buc[c[j]]=1;
if(!buc[1])continue;
if(buc[3]&&!buc[2])continue; bool judge=1;
for(int j=1;j<n;j++)if(c[j-1]&&c[j]&&c[j-1]!=c[j])judge=0;
for(int j=0,ap=0;j<n;j++)
if(c[j]==2)break;
else if(buc[3]&&c[j]==3)judge=0;
if(!judge)continue; mp[i]=++cnt;
if((i>>(2*n-2)&3)==1)ed[cnt]=1; g[cnt]=(i&3)==1;
for(int j=0;j<n;j++)
for(int k=j+1;k<n;k++)
if(c[j]==c[k]&&c[j])
for(int l=j+1;l<k;l++)
if(c[l]!=c[j])
g[cnt]=0; for(int j=1;j<1<<n;j++){
for(int k=0;k<2*n;k++)f[k]=k;
for(int k=1;k<4;k++)
for(int l=0,pre=-1;l<n;l++)
if(c[l]==k){
if(~pre)merge(l,pre);
pre=l;
}
for(int k=0;k<n;k++){
if(c[k]&&(j>>k&1))merge(k,k+n);
if(k&&(j>>k&1)&&(j>>(k-1)&1))merge(k+n-1,k+n);
}
int one,legal=0,two=-1,msk=0;
for(int k=0;k<n;k++)if(c[k]==1){one=find(k); break;}
for(int k=0;k<n;k++)
if(j>>k&1){
int f=find(k+n);
if(f==one)msk+=1<<(2*k),legal=1;
else if(two==-1||f==two)two=f,msk+=2<<(2*k);
else msk+=3<<(2*k);
}
if(legal)tr[cnt][j]=msk;
}
}
for(int i=1;i<=cnt;i++)
for(int j=0;j<1<<n;j++)
tr[i][j]=mp[tr[i][j]];
for(int i=1;i<m;i++){
mcpy(t,g),mem(g,0);
for(int j=1;j<=cnt;j++)
for(int k=1;k<1<<n;k++)
if(tr[j][k])
add(g[tr[j][k]],t[j]);
}
for(int i=1;i<=cnt;i++)if(ed[i])add(ans,g[i]);
cout<<ans<<endl;
return 0;
}

AT695 マス目的更多相关文章

  1. DP 优化方法大杂烩 & 做题记录 I.

    标 * 的是推荐阅读的部分 / 做的题目. 1. 动态 DP(DDP)算法简介 动态动态规划. 以 P4719 为例讲一讲 ddp: 1.1. 树剖解法 如果没有修改操作,那么可以设计出 DP 方案 ...

  2. ng-class结合三目运算

    ng-class文档:https://docs.angularjs.org/api/ng/directive/ngClass 但是在实际项目中可能会用到三目运算,实例如下: <ul> &l ...

  3. Objective-C中的类目,延展,协议

    Objective-C中的类目(Category),延展(Extension),协议(Protocol)这些名词看起来挺牛的,瞬间感觉OC好高大上.在其他OOP语言中就没见过这些名词,刚看到这三个名词 ...

  4. 项 目 管 理 知 识 体 系 指 南 (PMBOK2008)

    项 目 管 理 知 识 体 系 指 南 (第4版) PMBOK2008 输入 工具与技术 输出 4.项目整合管理 4.1 制定项目章程 4.1.1.1 项目工作说明书 4.1.2.1 专家判断 4.1 ...

  5. Scrapy003-项目流程

    Scrapy003-项目流程 @(Spider)[POSTS] 前两篇文章我们了解到Scrapy的原理和安装的相关知识,这节就需要知道创建项目流程的小知识. 根据官方文档:http://scrapy- ...

  6. OC中协议, 类目, 时间, 延展, 属性

    只有继承和协议需要引IMPORT "头文件"; 必须接受marryprotocol协议, id<marryprotocol>基于类型的限定, 才能给实例变量赋值 @pr ...

  7. angularjs的三目运算

    前言:前几天写代码的时候遇到一个问题,有一个按钮,有"已关注"和"+关注"两种状态,需要对这两种状态的按钮的背景颜色进行区分,单后点击"已关注&quo ...

  8. Objective - C - 添加类目 - NSDate

    1.类目为系统内部的类或者是没有源代码的类添加方法,不有添加实例变量 2.添加的方法会成为原类的一部分,子类照样可以使用 3.类目的文件名为原类名+文件名 4.既可以添加实例方法,也可以添加类方法 X ...

  9. 【Python全栈笔记】03 [模块二] 16-17 Oct Set 集合,三目运算

    Set 集合 set - unordered collections of unique elements 创建一个set/一个空set # create a new set set1 = {1,2, ...

随机推荐

  1. 微信小程序的发布流程

    一.背景 在中大型的公司里,人员的分工非常仔细,一般会有不同岗位角色的员工同时参与同一个小程序项目.为此,小程序平台设计了不同的权限管理使得项目管理者可以更加高效管理整个团队的协同工作 以往我们在开发 ...

  2. UltraSoft - Alpha - 发布声明

    DDL_Killer Alpha版本发布声明 1. Alpha 阶段功能描述与版本实现 功能描述 设计原型 Alpha实现 登陆界面 注册界面 首页 日历视图 事项详情页 新建事项 列表视图 课程视图 ...

  3. [对对子队]会议记录4.19(Scrum Meeting10)

    今天已完成的工作 何瑞 ​ 工作内容:搭建第2关,基本完成第3关 ​ 相关issue:搭建关卡2.3 ​ 相关签入:4.19签入1 4.19签入2 刘子航 ​ 工作内容:完成关卡选择界面的设计图 ​ ...

  4. [no code][scrum meeting] Alpha 2

    项目 内容 会议时间 2020-04-07 会议主题 功能规格说明书review 会议时长 30min 参会人员 OCR组(肖思炀,赵涛)和产品经理 $( "#cnblogs_post_bo ...

  5. 【二食堂】Alpha - Scrum Meeting 5

    Scrum Meeting 5 例会时间:4.15 12:30 - 13:00 进度情况 组员 昨日进度 今日任务 李健 1. 主页搭建结束issue2. 与后端协商确定接口的设计3. 查找文本区域功 ...

  6. STM32直流电机启动(一)驱动电路的介绍

    驱动电路 典型的H桥驱动电路如下:要使电机旋转只需导通对角线上的两个三极管即可,如导通Q1,Q4,关闭Q2,Q4即可驱动电机正转:若想电机反向转动,即导通三极管Q2,Q3,关闭Q1,Q4.此时电路图可 ...

  7. Python课程笔记 (五)

    今天主要学习图形用户界面,更多的还是要我们自己去实际操作,课仿佛上了一半就完了,分享一下课程(这里在SixthClass)的源码: https://gitee.com/wang_ming_er/pyt ...

  8. linux&c 进程控制 课后习题

    (声明:本篇博客只是博主自己的理解,加以整理,目的是总结刚学过的进程知识,不一定绝对正确,非常愿意听客官您提出宝贵意见.) Q1:进程中的全局数据段(全局变量),局部数据段(局部变量),静态数据段的分 ...

  9. Git基本教程

    git的发展 Git 两周开发 Linus开发,主要是为了管理大量人员维护代码 Git分布式版本控制系统 基本命令 history:查看之前用过的命令 vimtutor git配置 查看配置 git ...

  10. Java多线程| 01 | 线程概述

    Java多线程| 01 | 线程概述 线程相关概念 进程与线程 进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是操作系统进行资源分配与调度的基本单位.可以把进程简单的理解 ...