洛谷P3272 [SCOI2011]地板(插头dp)
感谢大佬的教导->这里
容易注意到,本题的合法路径“L型地板”有一些特殊的地方:拐弯且仅拐弯一次。
这由于一条路径只有两种状态:拐弯过和没拐弯过,因此我们可以尝试着这样定义新的插头:
我们使用三进制,0代表没有插头,1代表没拐弯过的路径,2代表已经拐弯过的路径。
依然设当前转移到格子(x,y),设y-1号插头状态为p1,y号插头状态为p2。
那么会有下面的几种情况:
情况1:p1==0&&p2==0
这时我们有三种可选的策略:
①以当前位置为起点,从p1方向引出一条新的路径(把p1修改为1号插头)
②以当前位置为起点,从p2方向引出一条新的路径(把p2修改为1号插头)
③以当前位置为“L”型路径的转折点,向p1,p2两个方向均引出一个2号插头.
情况2:p1==0&&p2==1
由于p2节点还没有拐过弯,因此我们有2种可选的策略:
①继续直走,不拐弯,即上->下(把p1修改为1号插头,p2置0)
②选择拐弯,即上->右(把p2改为2号插头)
情况3:p1==1&&p2==0
这种情况和情况2类似
情况4:p1==0&&p2==2
由于p2节点已经拐过弯,所以我们有如下的两种策略:
情况5:p1==2&&p2==0
这种情况与情况4类似
情况6:p1==1&&p2==1
这种情况下,两块地板均没有拐过弯,因此我们可以在本格将这两块地板合并,形成一个合法的“L”型路径,并将本格看做他们的转折点。(把p1和p2都置为0)
至此,新插头定义的状态转移已经讨论完成。
不难发现,这种新的插头定义可以处理可能发生的所有可行情况。
然后上代码
//minamoto
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,HASH=,mod=;
int ans,n,m,lastx,lasty;char c[N][N];bool room[N][N];
struct node{
int val[HASH],key[HASH],Hash[HASH],sz;
inline void init(){
memset(val,,sizeof(val)),memset(Hash,,sizeof(Hash));
memset(key,-,sizeof(key)),sz=;
}
inline void newhash(int id,int state){Hash[id]=++sz,key[sz]=state;}
inline int &operator [](const int state){
for(int i=state%HASH;;i=(i+==HASH)?:i+){
if(!Hash[i]) newhash(i,state);
if(key[Hash[i]]==state) return val[Hash[i]];
}
}
}f[];
inline int find(int state,int pos){return (state>>((pos-)<<))&;}
inline void set(int &state,int pos,int val){
pos=(pos-)<<,state|=<<pos,state^=<<pos,state^=val<<pos;
}
void solve(int x,int y){
int now=((x-)*m+y)&,last=now^,tot=f[last].sz;
f[now].init();
for(int i=;i<=tot;++i){
int state=f[last].key[i],val=f[last].val[i];
int plug1=find(state,y),plug2=find(state,y+);
if(!room[x][y]){
if(!plug1&&!plug2) (f[now][state]+=val)%=mod;
}
else{
if(!plug1&&!plug2){
if(room[x+][y]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
if(room[x][y+]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
if(room[x][y+]&&room[x+][y]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
}
else if(!plug1&&plug2){
if(plug2==){
if(room[x+][y]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
if(room[x][y+]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
}
else{
set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
if(x==lastx&&y==lasty&&!state) (ans+=val)%=mod;
if(room[x+][y]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
}
}
else if(plug1&&!plug2){
if(plug1==){
if(room[x][y+]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
if(room[x+][y]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
}
else{
set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
if(x==lastx&&y==lasty&&!state) (ans+=val)%=mod;
if(room[x][y+]) set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
}
}
else if(plug1==&&plug2==){
set(state,y,),set(state,y+,),(f[now][state]+=val)%=mod;
if(x==lastx&&y==lasty&&!state)(ans+=val)%=mod;
}
}
}
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i) scanf("%s",c[i]+);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
room[i][j]=(c[i][j]=='_');
if(m>n){
for(int i=;i<=n;++i)
for(int j=i+;j<=m;++j)
swap(room[i][j],room[j][i]);
swap(n,m);
}
int flag=;
for(int i=n;i&&flag;--i)
for(int j=m;j&&flag;--j)
if(room[i][j]){lastx=i,lasty=j;flag=;}
f[].init(),f[][]=;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j) solve(i,j);
if(i!=n)
for(int j=,last=(i*m)&,tot=f[last].sz;j<=tot;++j)
f[last].key[j]<<=;
}
printf("%d\n",ans);
return ;
}
洛谷P3272 [SCOI2011]地板(插头dp)的更多相关文章
- bzoj 2331: [SCOI2011]地板 插头DP
		
2331: [SCOI2011]地板 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 541 Solved: 239[Submit][Status] D ...
 - 【BZOJ2331】[SCOI2011]地板 插头DP
		
[BZOJ2331][SCOI2011]地板 Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里 ...
 - 2331: [SCOI2011]地板 插头DP
		
国际惯例的题面:十分显然的插头DP.由于R*C<=100,所以min(R,C)<=10,然后就可以愉悦地状压啦.我们用三进制状压,0表示没有插头,1表示有一个必须延伸至少一格且拐弯的插头, ...
 - 【BZOJ】2331: [SCOI2011]地板 插头DP
		
[题意]给定n*m的地板,有一些障碍格,要求用L型的方块不重不漏填满的方案数.L型方块是从一个方格向任意两个相邻方向延伸的方块,不能不延伸.n*m<=100. [算法]插头DP [题解]状态0表 ...
 - BZOJ 2331 [SCOI2011]地板 ——插头DP
		
[题目分析] 经典题目,插头DP. switch 套 switch 代码瞬间清爽了. [代码] #include <cstdio> #include <cstring> #in ...
 - 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)
		
洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\).我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...
 - P3272 [SCOI2011]地板(插头DP)
		
[题面链接] https://www.luogu.org/problemnew/show/P3272 [题目描述] 有一个矩阵,有些点必须放,有些点不能放,用一些L型的图形放满,求方案数 [题解] ( ...
 - [SCOI2011][bzoj2331] 地板 [插头dp]
		
题面: 传送门 思路: 插头dp基础教程 这个L形......第一眼看上去真的是丧病啊 但是仔细想想,实际上也就是拿一堆路径铺满一个棋盘,这个路径还是有限制的 那还有什么好说的,插头dp上啊[雾] 首 ...
 - 洛谷2344 奶牛抗议(DP+BIT+离散化)
		
洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...
 
随机推荐
- Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'URIType' of bean class
			
查阅了资料原始JDK的问题.解决方法 1.重新安装JDK为1.7版本 2.修改配置 1.webx的依赖改为3.1.6版: <dependency> <groupId>com.a ...
 - okhttp 特点  module版本冲突  集成module到项目
			
特点适合大小文件上传.下载,但对图片不会执行缓存是一个缺点 集成module到项目 右上角添加 lib和module版本冲突问题,删除lib下的即可
 - jQuery 的文档操作
			
在 js 中也有DOM操作,也可以进行 增删改查 ,但是通过 js 的DOM操作会发现,我的天哪,代码好多.但是 jQuery的文档操作就少了很多. js 中 DOM 的示例 : var box = ...
 - java入门了解05
			
1.模板模式 (一)需求:解决默写事情有固定模式,但有时内部会发生变化,此时就需要应用模板模式编写此过程 从而解决事情的流程依然可以别使用,这就是模板模式的好处(类似我们的个人简历模板) (二)步骤: ...
 - zabbix 上  mysql 优化
			
摘自: https://segmentfault.com/a/1190000001638101
 - (转)select、poll、epoll之间的区别总结[整理]
			
select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但select ...
 - 集训Day12
			
快乐 快乐就完事了 今天把Trie树 / 可持久化Trie树搞了一下 Trie树可以维护区间最大异或和 具体就是区间异或和 -> 区间两个前缀异或和的异或 然后就变成了 "从n个数里找 ...
 - jQuery bootstrap框架下重置下拉框选择
			
前端页面中下拉选择框采用bootstrap-select美化,如下图:
 - python 动态添加属性及方法及“__slots__的作用”
			
1.动态添加属性 class Person(object): def __init__(self, newName, newAge): self.name = newName self.age = n ...
 - scala & spark实战
			
java.lang.Long is not a valid external type for schema of string java.lang.RuntimeException: Error ...