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 マス目的更多相关文章
- DP 优化方法大杂烩 & 做题记录 I.
标 * 的是推荐阅读的部分 / 做的题目. 1. 动态 DP(DDP)算法简介 动态动态规划. 以 P4719 为例讲一讲 ddp: 1.1. 树剖解法 如果没有修改操作,那么可以设计出 DP 方案 ...
- ng-class结合三目运算
ng-class文档:https://docs.angularjs.org/api/ng/directive/ngClass 但是在实际项目中可能会用到三目运算,实例如下: <ul> &l ...
- Objective-C中的类目,延展,协议
Objective-C中的类目(Category),延展(Extension),协议(Protocol)这些名词看起来挺牛的,瞬间感觉OC好高大上.在其他OOP语言中就没见过这些名词,刚看到这三个名词 ...
- 项 目 管 理 知 识 体 系 指 南 (PMBOK2008)
项 目 管 理 知 识 体 系 指 南 (第4版) PMBOK2008 输入 工具与技术 输出 4.项目整合管理 4.1 制定项目章程 4.1.1.1 项目工作说明书 4.1.2.1 专家判断 4.1 ...
- Scrapy003-项目流程
Scrapy003-项目流程 @(Spider)[POSTS] 前两篇文章我们了解到Scrapy的原理和安装的相关知识,这节就需要知道创建项目流程的小知识. 根据官方文档:http://scrapy- ...
- OC中协议, 类目, 时间, 延展, 属性
只有继承和协议需要引IMPORT "头文件"; 必须接受marryprotocol协议, id<marryprotocol>基于类型的限定, 才能给实例变量赋值 @pr ...
- angularjs的三目运算
前言:前几天写代码的时候遇到一个问题,有一个按钮,有"已关注"和"+关注"两种状态,需要对这两种状态的按钮的背景颜色进行区分,单后点击"已关注&quo ...
- Objective - C - 添加类目 - NSDate
1.类目为系统内部的类或者是没有源代码的类添加方法,不有添加实例变量 2.添加的方法会成为原类的一部分,子类照样可以使用 3.类目的文件名为原类名+文件名 4.既可以添加实例方法,也可以添加类方法 X ...
- 【Python全栈笔记】03 [模块二] 16-17 Oct Set 集合,三目运算
Set 集合 set - unordered collections of unique elements 创建一个set/一个空set # create a new set set1 = {1,2, ...
随机推荐
- 【Java虚拟机2】Java类加载机制
前言 JAVA代码经过编译从源码变为字节码,字节码可以被JVM解读,使得JVM屏蔽了语言级别的限制.才有了现在的kotlin.Scala.Clojure.Groovy等语言. 字节码文件中描述了类的各 ...
- 计算机网络:HTTP
计算机网络基础:HTTP 先验知识 HTTP和其他协议的关系 通过下图,了解IP协议,TCP协议,DNS服务在使用HTTP协议通信过程中各自发挥的作用: 服务器处理流程 接受客户端连接 ------& ...
- logstash multi pipeline的使用
logstash multi pipeline的使用 一.背景 二.解决方案 1.方案一: 2.方案二: 3.方案三: 三.实现步骤 1.编写 pipeline 文件 1.从文件收集,输出到控制台 2 ...
- 链地址法查找成功与不成功的平均查找长度ASL
晚上,好像是深夜了,突然写到这类题时遇到的疑惑,恰恰这个真题只让计算成功的ASL,但我想学一下不成功的计算,只能自己来解决了,翻了李春葆和严蔚敏的教材没有找到相关链地址法的计算,于是大致翻到两篇不错的 ...
- 算法:杨辉三角(Pascal's Triangle)
一.杨辉三角介绍 杨辉三角形,又称帕斯卡三角形.贾宪三角形.海亚姆三角形.巴斯卡三角形,是二项式系数的一种写法,形似三角形,在中国首现于南宋杨辉的<详解九章算法>得名,书中杨辉说明是引自贾 ...
- python进阶(22)pydantic--数据类型校验
pydantic库的作用 pydantic库是一种常用的用于数据接口schema定义与检查的库. Pydantic 在运行时强制执行类型提示,并在数据无效时提供用户友好的错误信息. pydantic安 ...
- Linux 文本三剑客之 grep
Linux 系统中一切皆文件. 文件是个文本.可以读.可以写,如果是二进制文件,还能执行. 在使用Linux的时候,大都是要和各式各样文件打交道.熟悉文本的读取.编辑.筛选就是linux系统管理员的必 ...
- flex步局 11.02
语法 justify-content: flex-start | flex-end | center | space-between | space-around flex-start:弹性盒子元素将 ...
- 羽夏看Win系统内核——保护模式篇
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- 《手把手教你》系列技巧篇(三十九)-java+ selenium自动化测试-JavaScript的调用执行-上篇(详解教程)
1.简介 在做web自动化时,有些情况selenium的api无法完成,需要通过第三方手段比如js来完成实现,比如去改变某些元素对象的属性或者进行一些特殊的操作,本文将来讲解怎样来调用JavaScri ...