传送门

感谢大佬的教导->这里

容易注意到,本题的合法路径“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节点已经拐过弯,所以我们有如下的两种策略:

    ①路径在此停止。那么我们以本格作为L型路径的一个端点。如果当前处于最后一个非障碍格子,如果没有其他的插头,我们此时就可以统计答案了。
    ②路径延续。由于p2已经转弯过,因此我们只能选择继续直走,即上->下(把p1修改为2号插头,p2置0)和之前相似的方法把独立插头传递下去即可。

  情况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)的更多相关文章

  1. bzoj 2331: [SCOI2011]地板 插头DP

    2331: [SCOI2011]地板 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 541  Solved: 239[Submit][Status] D ...

  2. 【BZOJ2331】[SCOI2011]地板 插头DP

    [BZOJ2331][SCOI2011]地板 Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里 ...

  3. 2331: [SCOI2011]地板 插头DP

    国际惯例的题面:十分显然的插头DP.由于R*C<=100,所以min(R,C)<=10,然后就可以愉悦地状压啦.我们用三进制状压,0表示没有插头,1表示有一个必须延伸至少一格且拐弯的插头, ...

  4. 【BZOJ】2331: [SCOI2011]地板 插头DP

    [题意]给定n*m的地板,有一些障碍格,要求用L型的方块不重不漏填满的方案数.L型方块是从一个方格向任意两个相邻方向延伸的方块,不能不延伸.n*m<=100. [算法]插头DP [题解]状态0表 ...

  5. BZOJ 2331 [SCOI2011]地板 ——插头DP

    [题目分析] 经典题目,插头DP. switch 套 switch 代码瞬间清爽了. [代码] #include <cstdio> #include <cstring> #in ...

  6. 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)

    洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\)​​​​​.我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...

  7. P3272 [SCOI2011]地板(插头DP)

    [题面链接] https://www.luogu.org/problemnew/show/P3272 [题目描述] 有一个矩阵,有些点必须放,有些点不能放,用一些L型的图形放满,求方案数 [题解] ( ...

  8. [SCOI2011][bzoj2331] 地板 [插头dp]

    题面: 传送门 思路: 插头dp基础教程 这个L形......第一眼看上去真的是丧病啊 但是仔细想想,实际上也就是拿一堆路径铺满一个棋盘,这个路径还是有限制的 那还有什么好说的,插头dp上啊[雾] 首 ...

  9. 洛谷2344 奶牛抗议(DP+BIT+离散化)

    洛谷2344 奶牛抗议 本题地址:http://www.luogu.org/problem/show?pid=2344 题目背景 Generic Cow Protests, 2011 Feb 题目描述 ...

随机推荐

  1. iOS 分享功能开发

    iOS 开发过程中可能会遇到需要进行第三方分享的需求,比如向QQ,微信,微博等分享 如下图 我们今天要讲到的方式是使用了一个第三方工具: http://www.sharesdk.cn 一,注册账号 去 ...

  2. Android Weekly Notes Issue #317

    July 8th, 2018 Android Weekly Issue #317 本期主要内容包括"重磅"的Udacity放弃RN(其实是因为他们RN写的那个Feature不要了) ...

  3. Android Weekly Notes Issue #320

    Android Weekly Issue #320 July 29th, 2018 Android Weekly Issue #320 本期内容包括: Firebase的MLKit; 关于写Andro ...

  4. webpack笔记1

    1.设置多个入口起点 多用于提取公共类库 a.利用commonChunkPlugin const webpack= require('webpack'); const path = require(' ...

  5. 2014暑假ACM训练总结

    2014暑假ACM训练总结报告 匆匆之中,一个暑假又过去了,在学校训练的这段日子真的是感觉日子过得好快啊! 时光如箭,日月如梭! 匆忙的学习之中一个暑假就这样结束了,现在就来写一些总结吧,供自己以后阅 ...

  6. poj2965 The Pilots Brothers' refrigerator —— 技巧性

    题目链接:http://poj.org/problem?id=2965 题解:自己想到的方法是枚举搜索,结果用bfs和dfs写都超时了.网上拿别人的代码试一下只是刚好不超时的,如果自己的代码在某些方面 ...

  7. Servlet传递数据方式

    Servlet传递数据方式 基本概述 Servlet传递数据的方式有很多,这里提供五种方式: 1.静态变量 2.HttpServletResponse的sendRedirect()方法 3.HttpS ...

  8. (转)HLS协议,html5视频直播一站式扫盲

    本文来自于腾讯bugly开发者社区,原文地址:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1277 视频直播这么火,再不学就 ou ...

  9. CodeForces - 592D: Super M(虚树+树的直径)

    Ari the monster is not an ordinary monster. She is the hidden identity of Super M, the Byteforces’ s ...

  10. 51nod_1236_序列求和 V3 _组合数学

    51nod_1236_序列求和 V3 _组合数学 Fib(n)表示斐波那契数列的第n项,Fib(n) = Fib(n-1) + Fib(n-2).Fib(0) = 0, Fib(1) = 1. (1, ...