题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4804

题目大意

给你一个 \(n \times m\) 的矩形区域。你需要用 \(1 \times 1\) 和 \(1 \times 2\) 的砖块铺满这个区域,且满足如下要求:

  1. 所有的砖块可以竖着放或横着放;
  2. 砖角要放在格点上;
  3. \(1 \times 1\) 的砖不能少于 \(C\) 块也不能多于 \(D\) 块, \(1 \times 2\) 的砖没有数量限制。
  4. 有些方格在一开始就已经被填充了,这些方格不能被任何砖块覆盖。(在输入里用 0 表示这样的方格,用 1 表示普通方格)

请问有多少种满足上述规则的方案可以将矩形区域铺满?

解题思路

轮廓线动态规划,首先将状态压缩,1 表示这个格子现在被覆盖了, 0 表示没有被覆盖,这样可以把当前考虑的轮廓线上的 \(m\) 列的情况压缩成一个整数,然后按照这一回放什么砖、怎么放进行转移。

状态 \(f[now][s][k]\) 表示:当前位置(\(now\) 能够描绘出行号和列号,以滚动数组实现),以当前位置结尾的不确定状态为 \(s\) ,并且已经放了 \(k\) 个 \(1 \times 1\) 的砖块的方案总数。

进行完轮廓线DP后,答案即为 \(\sum_{i=C}^{D} f[now][(1<<m)-1][i]\) 。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1000000007LL;
int n, m, C, D;
long long f[2][1<<11][22];
char maze[101][11];
int main() {
while (~scanf("%d%d%d%d", &n, &m, &C, &D)) {
for (int i = 0; i < n; i ++) scanf("%s", maze[i]);
memset(f[0], 0, sizeof(f[0]));
int now = 0;
f[0][(1<<m)-1][0] = 1;
for (int i = 0; i < n; i ++) { // 遍历行号i
for (int j = 0; j < m; j ++) { // 遍历列号j
now = now ^ 1;
memset(f[now], 0, sizeof(f[now]));
for (int k = 0; k <= D; k ++) { // 遍历放置前已放置1x1砖块个数k
for (int s = 0; s < (1<<m); s ++) { // 遍历放置前不确定点状态
int s2, k2;
/** 当前格子不能放 */
if (maze[i][j] == '0') {
if (s & (1<<(m-1))) { // 最前面格子也放了
s2 = (s<<1)^1, k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
}
/** 当前格子可以放 */
else { // maze[i][j] == '1'
/** 情况1:当前格子不放 */
if (s & (1<<(m-1))) {
s2 = (s<<1), k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
/** 情况2:当前格子放一个竖着2x1的砖块 */
if (i > 0 && !(s & (1<<(m-1)))) {
s2 = (s<<1)^1, k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
/** 情况3:当前格子放一个横着1x2的砖块 */
if (j > 0 && !(s & 1) && (s & (1<<(m-1)))) {
s2 = (s<<1)^3, k2 = k;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
/** 情况4:当前格子放一个1x1的砖块 */
if ( k < D && (s & (1<<(m-1))) ) {
s2 = (s<<1)^1, k2 = k+1;
s2 &= (1<<m)-1;
f[now][s2][k2] += f[now^1][s][k];
f[now][s2][k2] %= MOD;
}
}
}
}
}
}
long long ans = 0;
for (int i = C; i <= D; i ++) {
ans = (ans + f[now][(1<<m)-1][i]) % MOD;
}
printf("%lld\n", ans);
}
return 0;
}

2013 ACM-ICPC亚洲区域赛南京站C题 题解 轮廓线DP的更多相关文章

  1. 【2018 ICPC亚洲区域赛南京站 A】Adrien and Austin(博弈)

    题意: 有一排n个石子(注意n可以为0),每次可以取1~K个连续的石子,Adrien先手,Austin后手,若谁不能取则谁输. 思路: (1) n为0时的情况进行特判,后手必胜. (2) 当k=1时, ...

  2. 2018ACM-ICPC亚洲区域赛南京站I题Magic Potion(网络流)

    http://codeforces.com/gym/101981/attachments 题意:有n个英雄,m个敌人,k瓶药剂,给出每个英雄可以消灭的敌人的编号.每个英雄只能消灭一个敌人,但每个英雄只 ...

  3. 2015 ACM / ICPC 亚洲区域赛总结(长春站&北京站)

    队名:Unlimited Code Works(无尽编码)  队员:Wu.Wang.Zhou 先说一下队伍:Wu是大三学长:Wang高中noip省一:我最渣,去年来大学开始学的a+b,参加今年区域赛之 ...

  4. 2014ACM/ICPC亚洲区域赛牡丹江站汇总

    球队内线我也总水平,这所学校得到了前所未有的8地方,因为只有两个少年队.因此,我们13并且可以被分配到的地方,因为13和非常大的数目.据领队谁oj在之上a谁去让更多的冠军.我和tyh,sxk,doub ...

  5. 【2013 ICPC亚洲区域赛成都站 F】Fibonacci Tree(最小生成树+思维)

    Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him to do s ...

  6. 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-A ( ZOJ 3819 ) Average Score

    Average Score Time Limit: 2 Seconds      Memory Limit: 65536 KB Bob is a freshman in Marjar Universi ...

  7. ICPC2019 亚洲区域赛 南京站

    蒟蒻终于打完了人生的第一场ICPC了. 终榜去星后rank36,AG,和AU差几十罚时了. 虽有遗憾但总体也是正常发挥了. 不愿再去对比赛做什么回顾,甚至很不愿去想.很多题已经在能力之外,即便是平常熟 ...

  8. 2014ACM/ICPC亚洲区域赛牡丹江站现场赛-K ( ZOJ 3829 ) Known Notation

    Known Notation Time Limit: 2 Seconds      Memory Limit: 65536 KB Do you know reverse Polish notation ...

  9. 【2018 ICPC亚洲区域赛徐州站 A】Rikka with Minimum Spanning Trees(求最小生成树个数与总权值的乘积)

    Hello everyone! I am your old friend Rikka. Welcome to Xuzhou. This is the first problem, which is a ...

随机推荐

  1. 通过Ajax提交form表单来提交上传文件

    Ajax 提交form方式可以将form表单序列化 然后将数据通过data提交至后台,例如: $.ajax({      url : "http://localhost:8080/" ...

  2. div盒子或者图片并排居中

    要使div总是找不到原因居中很简单,float和display都可以实现,float就不说了,这里说一下display:line-block,比如四个或者多个div盒子,明明设置好了宽度后,总有一个上 ...

  3. Flex AIR应用换肤功能(Android和IOS)

    说明 换肤功能,即将整个应用的皮肤都进行更换,其实质,是动态加载swf文件的过程,而这些swf文件则有css文件编译而来. 关于换肤功能,在android和ios系统的实现方式是不同的.主要原因,是因 ...

  4. Python--day30--网络基础

    单波: 查找mac:

  5. [转]在eclipse中,用maven创建一个web项目工程

    1.在eclipse中用maven创建项目,右键new>>Maven Project 2.点击next继续 3.点击next继续,选择maven-archetype-webapp, 4.点 ...

  6. uni-app 生命周期函数

    应用生命周期 函数名 说明 onLaunch 当uni-app 初始化完成时触发(全局只触发一次) onShow 当 uni-app 启动,或从后台进入前台显示 onHide 当 uni-app 从前 ...

  7. P1107 栈

    题目描述 背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 push(将一个元素进栈). 栈的重要性不言 ...

  8. 21个项目玩转深度学习:基于TensorFlow的实践详解02—CIFAR10图像识别

    cifar10数据集 CIFAR-10 是由 Hinton 的学生 Alex Krizhevsky 和 Ilya Sutskever 整理的一个用于识别普适物体的小型数据集.一共包含 10 个类别的 ...

  9. 通过作用域链解析js函数一些难以理解的的作用域问题

    基本原理 js函数在执行时,系统会创建一个隐式的属性scope,scope中存储的是函数的作用域链. 通过对这个scope的分析,就能解释JavaScript中许多难以理解的问题: 例1: funct ...

  10. 【codeforces 749B】Parallelogram is Back

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...