[SCOI2011][bzoj2331] 地板 [插头dp]
题面:
思路:
这个L形......第一眼看上去真的是丧病啊
但是仔细想想,实际上也就是拿一堆路径铺满一个棋盘,这个路径还是有限制的
那还有什么好说的,插头dp上啊【雾】
首先。我们定义这道题中的一个插头代表着从这个格子往插头指向的方向可以伸展一个L形
但是整张图上的所有插头不可能只有一种,因此我们要分析,可以继续延伸的L形都有哪些限制呢?
我们知道,L形的一个特点就是拐了一个弯,而且只拐了一个弯,因此我们可以定义这样的两种插头:
插头1代表一个还没有拐过弯的L形的延伸,插头2则代表一个已经拐过弯的L形的延伸
这样我们解决了定义问题,接下来看如何分类讨论
第一种情况:当前状态下,当前格子上方和左方都没有插头
这时我们需要找一个L形来把这个格子填上,那么我们可能有三种决策:
决策一:给这个格子加一个二号下插头和一个二号右插头,此时这个格子是一个新的L形的拐角
决策二:给这个格子加一个一号下插头,此时相当于构建了一个先向下再向右的L形,从当前格子开始
决策三:给这个格子加一个一号右插头,此时相当于构建了一个先向右再向下的L形,从当前格子开始
第二种情况:当前状态下,当前格子上方有一个一号下插头,左方没有插头
这时相当于上面有一个L形的未拐弯的一边伸过来了,有两种决策:
决策一:L形不拐弯,继续向下延伸,当前格子只有一个一号下插头
决策二:L形在当前格子拐弯,L形向右延伸,当前格子只有一个二号右插头
第三种情况:当前状态下,当前格子左方有一个一号右插头,上方没有插头
与第二种情况类似,故不赘述
第四种情况:当前状态下,当前格子上方有一个二号下插头,左方没有插头
这时相当于上面有一个L形的拐过弯的一边伸过来了,有两种决策:
决策一:L形继续延伸,当前格子有一个二号下插头
决策二:L形在当前格子终止,当前格子没有插头
决策二时注意,如果当前处在最后一个没有障碍的格子,那么需要统计入最终答案
第五种情况:当前状态下,当前格子左方有一个二号右插头,上方没有插头
与第四种情况类似,故不赘述
第六种情况:当前状态下,当前格子左方和上方都有一号插头
此时相当于两条“臂”伸了过来,在当前格子相交,应该合并成一个L形
当前格子相当于一个L形的拐弯处,没有插头
我们发现,情况一和情况六已经覆盖了四种L形的摆放方式,同时也不会有一个二号插头一个一号插头或者两个二号插头的情况出现——它们被上文的六种情况限制了
故这种分类讨论方式可以覆盖所有情况
状态可以用四进制表示(比较快),因为状态数较多,放到哈希表里面,滚动数组处理即可
Code:
// luogu-judger-enable-o2
#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=,flag=;char ch=getchar();
while(ch>''||ch<''){
if(ch=='-') flag=-;
ch=getchar();
}
while(ch>=''&&ch<='') re=(re<<)+(re<<)+ch-'',ch=getchar();
return re*flag;
}
int n,m,x[][],cur,pre,ex,ey;
int st[][];ll ans[][],re;
int tot[],bit[],state[],st_tot,hash=;
struct edge{
int to,next;
}a[];
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=;tot[cur]=;ans[cur][]=;st[cur][]=;
for(i=;i<=n;i++){
for(j=;j<=tot[cur];j++) st[cur][j]<<=;
for(j=;j<=m;j++){
memset(state,,sizeof(state));st_tot=;
pre=cur;cur^=;tot[cur]=;
for(k=;k<=tot[pre];k++){
now=st[pre][k];val=ans[pre][k];
right=(now>>bit[j-])%;down=(now>>bit[j])%;
if(!x[i][j]){//障碍格子
if(!down&&!right){
insert(now,val);continue;
}
}
if(!right&&!down){//第一种情况
if(x[i+][j]&&x[i][j+])
insert(now+((<<bit[j-])<<)+((<<bit[j])<<),val);
if(x[i+][j]) insert(now+(<<bit[j-]),val);
if(x[i][j+]) insert(now+(<<bit[j]),val);
}
if(right==&&!down){//第三种情况
if(x[i][j+]) insert(now-(<<bit[j-])+(<<bit[j]),val);
if(x[i+][j]) insert(now+(<<bit[j-]),val);
}
if(down==&&!right){//第二种情况
if(x[i+][j]) insert(now-(<<bit[j])+(<<bit[j-]),val);
if(x[i][j+]) insert(now+(<<bit[j]),val);
}
if(right==&&!down){//第五种情况
if(i==ex&&j==ey) re+=val,re%=MOD;
if(x[i][j+]) insert(now-((<<bit[j-])<<)+((<<bit[j])<<),val);
insert(now-((<<bit[j-])<<),val);
}
if(down==&&!right){//第四种情况
if(i==ex&&j==ey) re+=val,re%=MOD;
if(x[i+][j]) insert(now-((<<bit[j])<<)+((<<bit[j-])<<),val);
insert(now-((<<bit[j])<<),val);
}
if(down==&&right==){//第六种情况
if(i==ex&&j==ey) re+=val,re%=MOD;
insert(now-(<<bit[j-])-(<<bit[j]),val);
}
}
}
}
}
int main(){
int i,j;char ch;
n=read();m=read();
for(i=;i<=;i++) bit[i]=i<<;
if(n>m){
for(i=;i<=n;i++){
for(j=;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>;i--){
for(j=;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);
}
[SCOI2011][bzoj2331] 地板 [插头dp]的更多相关文章
- bzoj 2331: [SCOI2011]地板 插头DP
2331: [SCOI2011]地板 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 541 Solved: 239[Submit][Status] D ...
- 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 ...
- 【BZOJ2331】[SCOI2011]地板 插头DP
[BZOJ2331][SCOI2011]地板 Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里 ...
- [BZOJ2331]地板(插头DP)
Description lxhgww的小名叫"小L",这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板 ...
- P3272 [SCOI2011]地板(插头DP)
[题面链接] https://www.luogu.org/problemnew/show/P3272 [题目描述] 有一个矩阵,有些点必须放,有些点不能放,用一些L型的图形放满,求方案数 [题解] ( ...
- [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)
转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样 ...
- 插头dp初探
问题描述 插头dp用于解决一类可基于图连通性递推的问题.用插头来表示轮廓线上的连通性,然后根据连通性与下一位结合讨论进行转移. 表示连通性的方法 与字符串循环最小表示不同,这种方法用于给轮廓线上的联通 ...
随机推荐
- Java环境变量搭建(Windows环境)
变量名:JAVA_HOME 变量值:C:\Program Files (x86)\Java\jdk1.8.0_91 // 要根据自己的实际路径配置 变量名:CLASSPATH 变量值:. ...
- Jmeter模拟http请求
一.获取用户信息(GET请求):http://hostname/getuser?userid=1 1.打开jmeter,创建一个线程组,再添加一个http请求Sampler 2.设置域名.路径.请求方 ...
- Java连接MySQL数据库实现用户名密码的验证方法 Java语句中sql查询语句'' ""作用
//方法一,可以验证登录,但方法不实用.package com.swift; import java.sql.Connection; import java.sql.DriverManager; im ...
- Arguments Optional-freecodecamp算法题目
Arguments Optional 1.要求 创建一个计算两个参数之和的 function.如果只有一个参数,则返回一个 function,该 function 请求一个参数然后返回求和的结果. 如 ...
- 第27题:Leetcode226: Invert Binary Tree反转二叉树
翻转一棵二叉树. 示例: 输入: 4 / \ 2 7 / \ / \ 1 3 6 9 输出: 4 / \ 7 2 / \ / \ 9 6 3 1 思路 如果根节点存在,就交换两个子树的根节点,用递归 ...
- 数据结构(C语言)分享笔记:数据结构的逻辑层次、存储层次
[1] 严格意义上数据结构的概念 数据结构,一个简单的定义:相互之间存在一种或多种特定关系的数据元素的集合.即:数据结构 = 元素集合 + 元素间关系的集合 . 在讨论数据结构时,可以基于两个不同的层 ...
- js数组中去重对象
var allCourses = new Array();var coursesId = new Array();function findCourses() { Courses.data().eac ...
- k8s的储存方式简述
pod中的存储卷类型:1.emptyDir:用于临时储存空间,无持久性储存功能,生命周期同pod容器,pod删除后,数据不再存在.2.gitRepo:pod创建时,自动将云端仓库中的文件克隆到pod挂 ...
- JsRender (js模板引擎)
最近学习了一下Jsrender模板渲染工具,非常不错,功能比较强大,官网说他是“简单直观 功能强大 可扩展的 快如闪电”确实如此.总结一下!! jsRender 三个最重要的概念:模板.容器和数据. ...
- pandas库Series类型与基本操作
pandas读取excel的类型是dataFrame,然后提取每一列是一个Series类型 Series类型包括index和values两部分 a = pd.Series({'a':1,'b':5}) ...