题目链接: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. behavior planning——12.example cost funtion -lane change penalty

      In the image above, the blue self driving car (bottom left) is trying to get to the goal (gold sta ...

  2. Scrapy五大核心组件简介

    五大核心组件 scrapy框架主要由五大组件组成,他们分别是调度器(Scheduler),下载器(Downloader),爬虫(Spider),和实体管道(Item Pipeline),Scrapy引 ...

  3. Java Annotation详解(一): 理解和使用Annotation

    JDK1.5之后,引入了元数据的概念,也就是Annotation(注释),其实它是代码里的特殊标记,这些标记可以再编译.类加载.运行时被读取,并执行相应的处理. 元数据的作用: 如果要对于元数据的作用 ...

  4. 基于ThinkPHP与阿里大于的PHP短信验证功能

    https://blog.csdn.net/s371795639/article/details/53381274 PHP阿里大鱼短信验证 第一步 登陆阿里大于注册账号,在用户管理中心创建应用,确定A ...

  5. LuaForWindows_v5.1.4-45和lua-5.1.4.tar.gz

    Lua学习笔记(一) 安装调试环境 Lua学习笔记(一) 安装调试环境     觉得自己是该掌握一门脚本语言的时候了,虽然曾经用过C# 和JavaScript 写过Unity3D的脚本.但是,总觉得那 ...

  6. TP5单例模式操作Model

    tp5单例模式的代码实现 为什么要使用单例模式 使用单例模式实现逻辑处理与数据库操作分离能很大提升mysql的sql处理能力,并且易于维护 ArticleModel.php <?php name ...

  7. uni-app学习记录04-轮播图和滑屏图片

    <template> <view> <!-- 轮播图视图 swiper-item是每页的元素 --> <swiper :indicator-dots=&quo ...

  8. servicemix-3.2.1 内置的服务引擎和绑定组件

    服务引擎: servicemix-bean servicemix-camel servicemix-cxf-se servicemix-drools servicemix-eip servicemix ...

  9. 【u128】又一个数字游戏

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 小明拿出了一个素数集合,{2, 3, 5, 7, 11, 13, -, 127, -},他发现,从小到 ...

  10. H3C 路由表查找规则(3)