题目链接: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. @codeforces - 1205B@ Shortest Cycle

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个长度为 n 的正整数序列 a1, a2, ..., an ...

  2. [***]HZOI20190714 T2熟练剖分

    这题真的神仙,蒟弱表示看题解看不懂……std看了几个小时大概看懂,还有一些细节的东西没有思考. 最难受的是题解和std好像并不是同一个人写的……数组状态不一样……看了好久才看出来f也是前缀和. F[i ...

  3. WPS修订功能的使用

    WPS设置 设置用户名: 修改之后的效果:

  4. saltStack_template

    模版使用 新建文件:vim dns.sls   vim file/resolv.conf   执行 : [root@server_client base]# salt \* state.sls dns ...

  5. E - Count on a tree 树上第K小

    主席树的入门题目,这道题的题意其实就是说,给你一棵树,询问在两个节点之间的路径上的区间第K小 我们如何把树上问题转换为区间问题呢? 其实DFS就可以,我们按照DFS的顺序,对线段树进行建树,那么这个树 ...

  6. Android Animation动画详解(二): 组合动画特效

    前言 上一篇博客Android Animation动画详解(一): 补间动画 我已经为大家介绍了Android补间动画的四种形式,相信读过该博客的兄弟们一起都了解了.如果你还不了解,那点链接过去研读一 ...

  7. Codeforces Round #167 (Div. 1 + Div. 2)

    C. Dima and Staircase 线段树维护区间最大值. D. Dima and Two Sequences 由于模数不一定为质数,所以通过拆分质因数来做阶乘取模. E. Dima and ...

  8. 2001年NOIP普及组复赛题解

    题目涉及算法: 数的计算:动态规划: 最大公约数和最小公倍数问题:质因数分解: 求先序排列:递归: 装箱问题:动态规划(纯0-1背包问题) 数的计算 题目链接:https://www.luogu.or ...

  9. Linux 查看kafka版本

    find /opt -name \*kafka_\* | head -1 | grep -o '\kafka[^\n]*'

  10. 第一种方式:cookie的优化与购物车实例

    一 Cookie 的优化 1.1 一般而言,我们设置cookie是在php中设置 例如: <?php setcookie('testKey1','hello world',0,'/'); //# ...