洛谷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 题目描述 ...
随机推荐
- 【python】python版本升级,从2.6.6升级到2.7.13
centos6.5系统自带了2.6.6版本的python,有时候为了项目上的需要,需要将python版本升级到2.7.13,下面介绍了如何进行升级. 说明:python从2.6升级到2.7会引发很多问 ...
- 服务器安装tensorflow导入模块报错Illegal instruction (core dumped)
在ubuntu上安装tensorflow后导入模块显示Illegal instruction (core dumped) 服务器的版本是Ubuntu 16.04.5 降低版本,成功导入模块 pip3 ...
- luoguP3769 [CH弱省胡策R2]TATT
luoguP3769 [CH弱省胡策R2]TATT PS:做这题前先切掉 P4148简单题,对于本人这样的juruo更助于理解,当然dalao就当练练手吧 题目大意: 现在有n个四维空间中的点,请求出 ...
- 《avascript 高级程序设计(第三版)》 ---第三章 基本概念
本章主要介绍Javasript语言的一些语法: 1.严格模式:开启:"use strict"; 2.变量:全部用var来定义,在函数中使用的称为局部变量,不能全局使用. 3.数据类 ...
- ES6中promise总结
一.什么是ES6的Promise 讲太多也没有.直接在打印出来就好,console.dir(Promise) Promise 是一个构造函数,自身有all, reject, resolve 这几个眼熟 ...
- 2017SN多校D1T2 note:dp
题意: 给你一个长度为n的字符串s,并且告诉你有m对字母不能相邻,问你最少在s中取出多少个字符能够使这个字符串合法. 题解: 表示状态: dp[i] = max num of letters 考虑到第 ...
- IDEAL葵花宝典:java代码开发规范插件 lombok 插件
前言: lombok简介: lombok是暑假来到公司实习的时候发现的一个非常好用的小工具,刚见到的时候就感觉非常惊艳,有一种相见恨晚的感觉,用了一段时间之后感觉的确挺不错,所以特此来推荐一下. 那么 ...
- Log4j2_学习_01_Log4j 2使用教程
一.推荐使用的log4j2.xml <?xml version="1.0" encoding="UTF-8"?> <!-- 设置log4j2的 ...
- L87
Fear Makes Art More Engaging Emmanuel Kant spoke often about the sublime, and specifically how art b ...
- k8s-集群状态及部署一个实例
[root@k8s-master ~]# kubectl get csNAME STATUS MESSAGE ERRORcontroller-manager Healthy ok scheduler ...