P3272 [SCOI2011]地板(插头DP)
[题面链接] 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)的更多相关文章
- 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 ...
- [SCOI2011][bzoj2331] 地板 [插头dp]
题面: 传送门 思路: 插头dp基础教程 这个L形......第一眼看上去真的是丧病啊 但是仔细想想,实际上也就是拿一堆路径铺满一个棋盘,这个路径还是有限制的 那还有什么好说的,插头dp上啊[雾] 首 ...
- P3272 [SCOI2011]地板
\(\color{#0066ff}{ 题目描述 }\) lxhgww的小名叫"小L",这是因为他总是很喜欢L型的东西.小L家的客厅是一个R*C的矩形,现在他想用L型的地板来铺满整个 ...
- 洛谷P3272 [SCOI2011]地板(插头dp)
传送门 感谢大佬的教导->这里 容易注意到,本题的合法路径“L型地板”有一些特殊的地方:拐弯且仅拐弯一次. 这由于一条路径只有两种状态:拐弯过和没拐弯过,因此我们可以尝试着这样定义新的插头: 我 ...
- 插头dp小结
插头dp: \(A:\)插头dp是什么? \(B:\)一种基于连通性状态压缩的动态规划问题 \(A:\)请问有什么应用呢? \(B:\)各种网格覆盖问题,范围允许状压解决,常用于计算方案数与联通块权值 ...
随机推荐
- nested exception is java.net.UnknownHostException: mybatis.org异常处理
最近自己写了个小项目(丛林商城V1.0),一个简单的网上商铺:主界面是商品的展示和登录,面对三种角色的人群:一般客户,VIP客户,管理员,与之对应的三种商品价格,登陆后根据具体角色来显示商品的价格:还 ...
- bitcode编译错误
xcode编译引用的静态库可能会出现编译错误: does not contain bitcode. You must rebuild it with bitcode enabled (Xcode se ...
- DAY7-面向对象之绑定方法与非绑定方法
一.类中定义的函数分成两大类 一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入): 1. 绑定到类的方法:用classmethod装饰器装饰的方法. 为类量身定制 类.boud_met ...
- python爬虫(4)--Cookie的使用
Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密) 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的.那么 ...
- 使用myeclipse自动导入hibernate3的jar包,如何关联hibernate源码的解决办法
1.在网上找了好久,今天终于解决了,如果你的myeclipse自动生成的添加hibernate3jar包时,依靠通常的方法是无法关联其相应版本的源代码的,就是你在编写代码是,按住ctrl + hibe ...
- 关于jdk1.5之后的自定拆装箱
我们都知道jdk在1.5版本之后,增加了一些新特性,我们称之为语法糖,有:1.泛型,2.foreach增强for循环,3.自动拆装箱,4.可变参数,5.枚举,6.静态导入 public class T ...
- 使用Java创建JSON数据
--------------siwuxie095 工程名:TestCreateJSON 包名:com.siwuxie095.json 类名:Cr ...
- 托盘在XP下不能显示tooltip,在Vista和Windows7下正常
转自:http://blog.csdn.net/debehe/article/details/4294053 奇怪的问题,想了很多可能的理由,最终的答案竟然是一开始就被我否认了的一种可能!! 问题现象 ...
- JS对表单的操作
JS对表单中的style的操作,包括复选框技术 废话不多说直接上文件代码!!! 功能:全选\反选,鼠标监测变颜色 <html> <head> <meta charset= ...
- Linux网络服务管理命令
netstat命令 示例:查看指定的服务是否开启netstat | grep ssh | grep -v grep 网络下载器————wget wget是一个Linux环境下用于从WWW上提取文件的工 ...