P3272 [SCOI2011]地板
\(\color{#0066ff}{ 题目描述 }\)
lxhgww的小名叫”小L“,这是因为他总是很喜欢L型的东西。小L家的客厅是一个R*C的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。
铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
\(\color{#0066ff}{输入格式}\)
输入的第一行包含两个整数,R和C,表示客厅的大小。接着是R行,每行C个字符。'_'表示对应的位置是空的,必须铺地板;'*'表示对应的位置有柱子,不能铺地板。
\(\color{#0066ff}{输出格式}\)
输出包含q行,第i行为m[i]个整数,该行的第j(j=1,2...,,m[i])个数表示第i年被授权的聚居地h[j]的临时议事处管理的种族个数。
\(\color{#0066ff}{输入样例}\)
3 3
___
_*_
___
\(\color{#0066ff}{输出样例}\)
8
\(\color{#0066ff}{数据范围与提示}\)
测试点编号 数据范围
1,2 R*C<=25
3-5 R*C<=100并且(R=2或者C=2)
6-10 R*C<=100
\(\color{#0066ff}{ 题解 }\)
一道不错的插头DP
情况要考虑全面
考虑插头,0:无,1:未拐弯插头,2:已拐弯插头(题中要求必须是拐弯的砖)
套板子就行啦
再次声明,我TM就不写hash表,暴力卡常开\(O2\),980ms卡过去!!!
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
std::unordered_map<int, int> f[2];
int n, m, s, t;
bool mp[120][120];
char getch() {
char ch = getchar();
while(ch != '*' && ch != '_') ch = getchar();
return ch;
}
void init() {
n = in(), m = in();
static bool cp[120][120];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cp[i][j] = getch() == '_';
if(m > n) {
std::swap(n, m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
mp[i][j] = cp[j][i];
if(mp[i][j]) s = i, t = j;
}
}
else {
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) {
mp[i][j] = cp[i][j];
if(mp[i][j]) s = i, t = j;
}
}
}
const int mod = 20110520;
int pos(int v, int x) { return (v << (x << 1LL)); }
void ins(int &x, int y) { x %= mod, (x += y) %= mod; }
int work() {
int now = 0, nxt = 1;
int ans = 0;
f[now][0] = 1;
int U = (1 << ((m + 1) << 1)) - 1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
f[nxt].clear();
for(auto &k:f[now]) {
int S = k.first, val = k.second;
int L = (S >> ((j - 1) << 1)) & 3, R = (S >> (j << 1)) & 3;
if(!mp[i][j]) {
if(!L && !R) ins(f[nxt][S], val);
continue;
}
if(!L && !R) {
//right 1
if(mp[i][j + 1]) ins(f[nxt][S ^ pos(1, j)], val);
//down 1
if(mp[i + 1][j]) ins(f[nxt][S ^ pos(1, j - 1)], val);
//middle double 2
if(mp[i][j + 1] && mp[i + 1][j]) ins(f[nxt][S ^ pos(2, j - 1) ^ pos(2, j)], val);
}
//要么直走还是1,要么拐弯变成2
else if(L == 0 && R == 1) {
if(mp[i + 1][j]) ins(f[nxt][S ^ pos(1, j - 1) ^ pos(1, j)], val);
if(mp[i][j + 1]) ins(f[nxt][S ^ pos(1, j) ^ pos(2, j)], val);
}
//要么直走还是2,要么停下变成0
else if(L == 0 && R == 2) {
if(mp[i + 1][j]) ins(f[nxt][S ^ pos(2, j - 1) ^ pos(2, j)], val);
ins(f[nxt][S ^ pos(2, j)], val);
}
//跟上面差不多
else if(L == 1 && R == 0) {
if(mp[i][j + 1]) ins(f[nxt][S ^ pos(1, j - 1) ^ pos(1, j)], val);
if(mp[i + 1][j]) ins(f[nxt][S ^ pos(1, j - 1) ^ pos(2, j - 1)], val);
}
else if(L == 2 && R == 0) {
if(mp[i][j + 1]) ins(f[nxt][S ^ pos(2, j - 1) ^ pos(2, j)], val);
ins(f[nxt][S ^ pos(2, j - 1)], val);
}
//必须拼上,没有其他情况
else if(L == 1 && R == 1) {
ins(f[nxt][S ^ pos(1, j - 1) ^ pos(1, j)], val);
}
//这些情况都是不成立的
else if(L == 1 && R == 2) {}
else if(L == 2 && R == 1) {}
else if(L == 2 && R == 2) {}
if(i == s && j == t) {
//1 1 // 0 2 // 2 0 第一个是接上,后两个是直接停下,都可以收集ans
if(L + R == 2) ins(ans, val);
}
}
std::swap(now, nxt);
}
f[nxt].clear();
for(auto &k:f[now]) ins(f[nxt][(k.first << 2) & U], k.second);
std::swap(nxt, now);
}
return ans;
}
int main() {
init();
printf("%d\n", work() % mod);
return 0;
}
P3272 [SCOI2011]地板的更多相关文章
- P3272 [SCOI2011]地板(插头DP)
[题面链接] https://www.luogu.org/problemnew/show/P3272 [题目描述] 有一个矩阵,有些点必须放,有些点不能放,用一些L型的图形放满,求方案数 [题解] ( ...
- 洛谷P3272 [SCOI2011]地板(插头dp)
传送门 感谢大佬的教导->这里 容易注意到,本题的合法路径“L型地板”有一些特殊的地方:拐弯且仅拐弯一次. 这由于一条路径只有两种状态:拐弯过和没拐弯过,因此我们可以尝试着这样定义新的插头: 我 ...
- 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型的地板来铺满整个客厅,客厅里 ...
- bzoj:2331: [SCOI2011]地板
Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板.现在小L想知道,用 ...
- 2331: [SCOI2011]地板 插头DP
国际惯例的题面:十分显然的插头DP.由于R*C<=100,所以min(R,C)<=10,然后就可以愉悦地状压啦.我们用三进制状压,0表示没有插头,1表示有一个必须延伸至少一格且拐弯的插头, ...
- BZOJ2331:[SCOI2011]地板——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2331 题面复制于洛谷 题目描述 lxhgww的小名叫”小L“,这是因为他总是很喜欢L型的东西.小L家 ...
- 【BZOJ】2331: [SCOI2011]地板 插头DP
[题意]给定n*m的地板,有一些障碍格,要求用L型的方块不重不漏填满的方案数.L型方块是从一个方格向任意两个相邻方向延伸的方块,不能不延伸.n*m<=100. [算法]插头DP [题解]状态0表 ...
- bzoj2331 [SCOI2011]地板
Description lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西.小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板.现在小L想知道,用 ...
随机推荐
- Redis codis 搭建测试
codis Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别,有部分命令支持 Codis ...
- c++ 端口扫描程序
第一.原理 端口扫描的原理很简单,就是建立socket通信,切换不通端口,通过connect函数,如果成功则代表端口开发者,否则端口关闭. 所有需要多socket程序熟悉,本内容是在window环境下 ...
- JavaScript语言基础-对象与数组
- DAY16-Django之model
Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...
- Tornado之抽屉实战(2)--数据库表设计
经过我们上次分析,数据库要有最基本的四张表,用户表,消息表,类型表,点赞表,评论表,接下来我们看着怎么设计吧 首先我们要清楚,表设计的代码是写在models下的 用户表 ? 1 2 3 4 5 6 7 ...
- Solr搜索的排序打分规则探讨
使用Solr搭建搜索引擎很容易,但是如何制定合理的打分规则(boost)做排序却是一个很头痛的事情.Solr本身的排序打分规则是继承自Lucene的文本相关度的打分即boost,这一套算法对于通用的提 ...
- Android LayoutInflater学习
在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById().不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例 ...
- java中一些常用的英语
abstract (关键字 ) 抽象 ['.bstr.kt] access vt.访问,存取 ['.kses]'(n.入口,使用权) algorithm n.算法 ['.lg.rie ...
- REST API (更新文档)
Elasticsearch的更新文档API准许通过脚本操作来更新文档.更新操作从索引中获取文档,执行脚本,然后获得返回结果.它使用版本号来控制文档获取或者重建索引. 我们新建一个文档: 请求:PUT ...
- [hdu1251]统计难题(trie模板题)
题意:返回字典中所有以测试串为前缀的字符串总数. 解题关键:trie模板题,由AC自动机的板子稍加改造而来. #include<cstdio> #include<cstring> ...