[题面链接] https://www.luogu.org/problemnew/show/P3272

[题目描述] 有一个矩阵,有些点必须放,有些点不能放,用一些L型的图形放满,求方案数

[题解] (版权所有) https://www.luogu.org/blog/dedicatus545/solution-p3272

第一种情况:当前状态下,当前格子上方和左方都没有插头

这时我们需要找一个L形来把这个格子填上,那么我们可能有三种决策:

  决策一:给这个格子加一个二号下插头和一个二号右插头,此时这个格子是一个新的L形的拐角

  决策二:给这个格子加一个一号下插头,此时相当于构建了一个先向下再向右的L形,从当前格子开始

  决策三:给这个格子加一个一号右插头,此时相当于构建了一个先向右再向下的L形,从当前格子开始

第二种情况:当前状态下,当前格子上方有一个一号下插头,左方没有插头

这时相当于上面有一个L形的未拐弯的一边伸过来了,有两种决策:

  决策一:L形不拐弯,继续向下延伸,当前格子只有一个一号下插头

  决策二:L形在当前格子拐弯,L形向右延伸,当前格子只有一个二号右插头

第三种情况:当前状态下,当前格子左方有一个一号右插头,上方没有插头

与第二种情况类似,故不赘述

第四种情况:当前状态下,当前格子上方有一个二号下插头,左方没有插头

这时相当于上面有一个L形的拐过弯的一边伸过来了,有两种决策:

  决策一:L形继续延伸,当前格子有一个二号下插头

  决策二:L形在当前格子终止,当前格子没有插头

决策二时注意,如果当前处在最后一个没有障碍的格子,那么需要统计入最终答案

第五种情况:当前状态下,当前格子左方有一个二号右插头,上方没有插头

与第四种情况类似,故不赘述

第六种情况:当前状态下,当前格子左方和上方都有一号插头

此时相当于两条“臂”伸了过来,在当前格子相交,应该合并成一个L形

当前格子相当于一个L形的拐弯处,没有插头

我们发现,情况一和情况六已经覆盖了四种L形的摆放方式,同时也不会有一个二号插头一个一号插头或者两个二号插头的情况出现——它们被上文的六种情况限制了

故这种分类讨论方式可以覆盖所有情况

总结

\(1.\) 插头定义在扫描线上方,定义处理前插头在左上的上方,处理完当前点后对应的扫描线图形后插头在右下的上方

\(2.\) 插头DP神题,注意分类讨论,一般分类标准为向右向下延伸,而向左向上的情况则通过在某一个点合并上面和左边传来的

//  https://www.luogu.org/blog/dedicatus545/solution-p3272
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define hash deep_dark_fantasy
#define ll long long
#define MOD 20110520
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,x[150][150],cur,pre,ex,ey;
int st[2][300010];ll ans[2][300010],re;
int tot[2],bit[20],state[300010],st_tot,hash=300000;
struct edge{
int to,next;
}a[300010];
void insert(int now,ll val){
int p=now%hash;
for(int i=state[p];i;i=a[i].next){
if(st[cur][a[i].to]==now){
ans[cur][a[i].to]+=val;
ans[cur][a[i].to]%=MOD;return;
}
}
tot[cur]++;
a[++st_tot].to=tot[cur];
a[st_tot].next=state[p];
state[p]=st_tot;st[cur][tot[cur]]=now;ans[cur][tot[cur]]=val%MOD;
}
void dp(){
int i,j,k,down,right,now;ll val;
cur=0;tot[cur]=1;ans[cur][1]=1;st[cur][1]=0;
for(i=1;i<=n;i++){
for(j=1;j<=tot[cur];j++) st[cur][j]<<=2;
for(j=1;j<=m;j++){
memset(state,0,sizeof(state));st_tot=0;
pre=cur;cur^=1;tot[cur]=0;
for(k=1;k<=tot[pre];k++){
now=st[pre][k];val=ans[pre][k];
right=(now>>bit[j-1])%4;down=(now>>bit[j])%4;
if(!x[i][j]){//障碍格子
if(!down&&!right){
insert(now,val);continue;
}
}
if(!right&&!down){//第一种情况
if(x[i+1][j]&&x[i][j+1])
insert(now+((1<<bit[j-1])<<1)+((1<<bit[j])<<1),val);
if(x[i+1][j]) insert(now+(1<<bit[j-1]),val);
if(x[i][j+1]) insert(now+(1<<bit[j]),val);
}
if(right==1&&!down){//第三种情况
if(x[i][j+1]) insert(now-(1<<bit[j-1])+(1<<bit[j]),val);
if(x[i+1][j]) insert(now+(1<<bit[j-1]),val);
}
if(down==1&&!right){//第二种情况
if(x[i+1][j]) insert(now-(1<<bit[j])+(1<<bit[j-1]),val);
if(x[i][j+1]) insert(now+(1<<bit[j]),val);
}
if(right==2&&!down){//第五种情况
if(i==ex&&j==ey) re+=val,re%=MOD;
if(x[i][j+1]) insert(now-((1<<bit[j-1])<<1)+((1<<bit[j])<<1),val);
insert(now-((1<<bit[j-1])<<1),val);
}
if(down==2&&!right){//第四种情况
if(i==ex&&j==ey) re+=val,re%=MOD;
if(x[i+1][j]) insert(now-((1<<bit[j])<<1)+((1<<bit[j-1])<<1),val);
insert(now-((1<<bit[j])<<1),val);
}
if(down==1&&right==1){//第六种情况
if(i==ex&&j==ey) re+=val,re%=MOD;
insert(now-(1<<bit[j-1])-(1<<bit[j]),val);
}
}
}
}
}
int main(){//这道题的读入没有保证n>=m,所以我写了一个判断,来保证n>=m,具体操作就是把图旋转了九十度
int i,j;char ch;
n=read();m=read();
for(i=1;i<=20;i++) bit[i]=i<<1;
if(n>m){
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
ch=getchar();
while(ch!='*'&&ch!='_') ch=getchar();
x[i][j]=(ch=='_');
if(x[i][j]) ex=i,ey=j;
}
}
}
else{
swap(n,m);
for(i=m;i>0;i--){
for(j=1;j<=n;j++){
ch=getchar();
while(ch!='*'&&ch!='_') ch=getchar();
x[j][i]=(ch=='_');
if(x[j][i]&&((j>ex)||(j==ex&&i>ey))) ex=j,ey=i;
}
}
}
dp();
printf("%lld",re);
}

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. [SCOI2011][bzoj2331] 地板 [插头dp]

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

  7. P3272 [SCOI2011]地板

    \(\color{#0066ff}{ 题目描述 }\) lxhgww的小名叫"小L",这是因为他总是很喜欢L型的东西.小L家的客厅是一个R*C的矩形,现在他想用L型的地板来铺满整个 ...

  8. 洛谷P3272 [SCOI2011]地板(插头dp)

    传送门 感谢大佬的教导->这里 容易注意到,本题的合法路径“L型地板”有一些特殊的地方:拐弯且仅拐弯一次. 这由于一条路径只有两种状态:拐弯过和没拐弯过,因此我们可以尝试着这样定义新的插头: 我 ...

  9. 插头dp小结

    插头dp: \(A:\)插头dp是什么? \(B:\)一种基于连通性状态压缩的动态规划问题 \(A:\)请问有什么应用呢? \(B:\)各种网格覆盖问题,范围允许状压解决,常用于计算方案数与联通块权值 ...

随机推荐

  1. spring中的class配置不能使用properties中的字符串

    1.比如在a.properties中我们声明了一个变量: classRoom=com.wc82.ClassRoom 2.然后在spring的配置文件中:applicationContext.xml,有 ...

  2. MS_SQL_获取字符串最后出现的字符串及位置

      一.如:'6.7.8.2.3.4.x'得到最后一个'.'后面的字符串: declare @str1 varchar(50) set @str1='6.7.8.2.3.4.x' select REV ...

  3. LINUX中错误 SELinux is disabled

    解决: setenforce: SELinux is disabled 那么说明selinux已经被彻底的关闭了 如果需要重新开启selinux,请按下面步骤: vi /etc/selinux/con ...

  4. Ros问题汇总

    1.ImportError: No module named beginner_tutorials.srv 解决: cd ~/catkin_ws $ source devel/setup.bash $ ...

  5. SpringBoot06 统一响应格式

    1 要求 每个请求成功后,后台返回的响应格式都是一致的,例如: 2 创建一个视图模型 该模型用于格式化响应数据 package cn.xiangxu.springboottest.model.data ...

  6. elasticsearch 6.2.4 安装 elasticsearch-analysis-ik 分词器 (windows 10下)

    访问 https://github.com/medcl/elasticsearch-analysis-ik  找 releases 找到对应的 es 版本 下载 elasticsearch-analy ...

  7. loj2436 糖果

    传送门 分析 我们知道对于一个不等式a<b可以将其转化为a+1<=b的形式,在知道这个之后我们便可以将5个关系进行差分约束了,具体的建边方式见代码.注意由于每个人都必须有糖,我们把每个人的 ...

  8. 及时修改jira的状态

    领到一个task,然后,修改task状态为开发状态,并且,点击edit,选择,story points,预估自己这个task大概做几天. 做完task后,再修改task的状态

  9. JS 求解时间差

    function UTCTimeDemo($str){ var d, s = "当前 UTC 时间为: "; var c = ":"; d = new Date ...

  10. 国内物联网平台(3):QQ物联智能硬件开放平台

    国内物联网平台(3)——QQ物联·智能硬件开放平台 马智 平台定位 将QQ帐号体系.好友关系链.QQ消息通道及音视频服务等核心能力提供给可穿戴设备.智能家居.智能车载.传统硬件等领域的合作伙伴,实现用 ...