hihoCoder 1048 : 状态压缩·二

题目链接http://hihocoder.com/problemset/problem/1048

题目大意:用1*2或者2*1的方块铺满一个N*M的大方格,共有多少种方法。结果对1e9+7取余。2<=N<=1000, 3<=m<=5

解题思路:挑战程序设计竞赛上有基本上一样的题目,可以参考,原题中也有提示。大致思路就是,如果从左往右铺的话,那么对第i行j列的方块来说,第i-1行的方块一定全部铺过,第j+2行的一定没有铺过。所以我们可以保存第i行和第i+1行的状态,然后递推。又由于m<=5,所以可以将两行的状态压缩成整数。具体递推过程:

 1 int t = 0;
 2 //位置(i, j)已经被铺
 3 if(s1 & (1 << k)){
 4     if(j < m) t = dp[i][j + 1][s1][s2];            //由下一个方块递推
 5     else if(i < n) t = dp[i + 1][1][s2][0];        //从下一行第一个递推
 6     else t = 0;
 7 }
 8 else{
 9     if(j < m && !(s1 & (1 << (k - 1))))         //可以横着铺
10         t += dp[i][j][s1 | (1 << k - 1) | (1 << k)][s2];
11     t %= mod;
12     if(i < n && !(s2 & (1 << k)))                 //可以竖着铺
13         t += dp[i][j][s1 | (1 << k)][s2 | (1 << k)];
14     t %= mod;
15 }
16 dp[i][j][s1][s2] += t % mod;                                            

完整代码:

 1 const int maxn = 1e3 + 5;
 2 int n, m;
 3 int dp[maxn][6][35][35];
 4
 5 void solve(){
 6     memset(dp, 0, sizeof(dp));
 7     for(int s2 = (1 << m) - 1; s2 >= 0; s2--) dp[n][m][(1 << m) - 1][s2] = 1;
 8     for(int i = n; i >= 1; i--){
 9         for(int j = m; j >= 1; j--){
10             int k = m - j;
11             for(int s1 = (1 << m) - 1; s1 >= 0; s1--){
12                 for(int s2 = (1 << m) - 1; s2 >= 0; s2--){
13                     int t = 0;
14                     //位置(i, j)已经被铺
15                     if(s1 & (1 << k)){
16                         if(j < m) t = dp[i][j + 1][s1][s2];            //由下一个方块递推
17                         else if(i < n) t = dp[i + 1][1][s2][0];        //从下一行第一个递推
18                         else t = 0;
19                     }
20                     else{
21                         if(j < m && !(s1 & (1 << (k - 1))))         //可以横着铺
22                             t += dp[i][j][s1 | (1 << k - 1) | (1 << k)][s2];
23                         t %= mod;
24                         if(i < n && !(s2 & (1 << k)))                 //可以竖着铺
25                             t += dp[i][j][s1 | (1 << k)][s2 | (1 << k)];
26                         t %= mod;
27                     }
28                     dp[i][j][s1][s2] += t % mod;
29                 }
30             }
31         }
32     }
33     printf("%d\n", dp[1][1][0][0]);
34 }
35 int main(){
36     scanf("%d %d", &n, &m);
37     solve();
38 }

题目:

#1048 : 状态压缩·二

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

历经千辛万苦,小Hi和小Ho终于到达了举办美食节的城市!虽然人山人海,但小Hi和小Ho仍然抑制不住兴奋之情,他们放下行李便投入到了美食节的活动当中。美食节的各个摊位上各自有着非常多的有意思的小游戏,其中一个便是这样子的:

小Hi和小Ho领到了一个大小为N*M的长方形盘子,他们可以用这个盒子来装一些大小为2*1的蛋糕。但是根据要求,他们一定要将这个盘子装的满满的,一点缝隙也不能留下来,才能够将这些蛋糕带走。

这么简单的问题自然难不倒小Hi和小Ho,于是他们很快的就拿着蛋糕离开了~

但小Ho却不只满足于此,于是他提出了一个问题——他们有多少种方案来装满这个N*M的盘子呢?

值得注意的是,这个长方形盘子的上下左右是有区别的,如在N=4, M=3的时候,下面的两种方案被视为不同的两种方案哦!

提示:我们来玩拼图吧!不过不同的枚举方式会导致不同的结果哦!

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第一行为两个正整数N、M,表示小Hi和小Ho拿到的盘子的大小。

对于100%的数据,满足2<=N<=1000, 3<=m<=5。<>

输出

考虑到总的方案数可能非常大,只需要输出方案数除以1000000007的余数。

样例输入
2 4
样例输出
5
时间: 2024-10-10 16:05:06

hihoCoder 1048 : 状态压缩·二的相关文章

HihoCoder第九周 状态压缩 二 与POJ2411总结

在此我向各位博友求助,特别想知道除了HihoCoder上面的结果要对1e9+7取余之外,这两道题还有什么其他的问题,都是骨牌覆盖问题,都是状态压缩+dp,为什么我能过poj2411的程序过不了HihoCoder,还不是其他诸如TimeLimited,而是Wrong Answer,这个问题我想了很久,还是不知道是怎么回事,如果有神通广大的博友知道答案,希望你能告诉我.顺便说一下,HihoCoder给的那个hint只看懂了一部分递推的公式,其中满足的那个条件还是不懂. 两个题目的连接地址: http

算法练习系列—hiho1044 状态压缩二(捡垃圾)

题目地址:http://hihocoder.com/problemset/problem/1044 算法思路:此题可以看做是铺地砖的变形,没有明显的行数和状态,但是我们可以自己将其中的行和状态给扣出来.其中第一行就是N个数的中前(0,1,2-M-1), 第二行就是(2,3..M)-一直到最后一行为(N-M-N).每一行的状态个数即为2^M-1(即这M个位置要么填写1,要么填写0).此时可用F[i][j]表示第i行状态为j时的垃圾最大值.最终的结果就是第N-M行所对应的状态中的最大值. 上一遍bl

[hihoCoder] 1044 : 状态压缩&#183;一

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市--那座城市即将举行美食节! 但是不幸的是,小Hi和小Ho并没有能够买到很好的火车票--他们只能够乘坐最为破旧的火车进行他们的旅程. 不仅如此,因为美食节的吸引,许多人纷纷踏上了和小Hi小Ho一样的旅程,于是有相当多的人遭遇到了和小Hi小Ho一样的情况--这导致这辆车上的人非常非常的多,以至于都没有足够的位置能让每

hihoCoder week8 状态压缩&#183;一

状态压缩  写了两个半小时  太菜了 题目链接 https://hihocoder.com/contest/hiho8/problem/1 #include <bits/stdc++.h> using namespace std; const int N = 10; const int MAXN = 1<<11; int n, m, q, w[MAXN]; // 存取到达i时候, 前面m-1个的状态 int dp[1024][MAXN]; int Count(int x) { in

hihoCoder #1044 : 状态压缩&#183;一 (清垃圾)

题意: 某车厢有一列座位,共有n个位置,清洁工要在这n个位置上清垃圾,但是不能全部位置都清理,只能选择部分.选择的规则是,连续的m个位置内,不能够清理超过q个,也就是说从第1~m个位置最多可以清q个,清q+1个就不行了.当然,q一般是小于m的,不然岂不是可以m个位置全清了?那就没限制了. 思路:看小hi小ho讲的完全是一知半解,看了大神的代码一整天才看懂意思.下面做分析(以我能理解的角度,以及通俗的角度,方便回忆.): 三个变量的定义: n: 一共有n个座位. m: 在m个连续的座位. q:最多

HihoCoder 1044 垃圾清理 状态压缩&#183;一

状态压缩·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市--那座城市即将举行美食节! 但是不幸的是,小Hi和小Ho并没有能够买到很好的火车票--他们只能够乘坐最为破旧的火车进行他们的旅程. 不仅如此,因为美食节的吸引,许多人纷纷踏上了和小Hi小Ho一样的旅程,于是有相当多的人遭遇到了和小Hi小Ho一样的情况--这导致这辆车上的人非常非常的多,以至于都没有足

算法练习系列—hiho1048 状态压缩一(铺地砖)

题目地址:http://hihocoder.com/problemset/problem/1048 编程之美的课后题也有一个和整个题目一样的.(P269) 题目 这个题目的题意很容易理解,在一个N*M的格子里,我们现在有两种类型的砖块,1 * 2和 2 * 1,问一共有多少种方案,可以将整个N*M的空间都填满. 最简单的例子就是下面的了: 编程之美中题目: 某年夏天,位于希格玛大厦四层的微软亚洲研究院对办公楼的天井进行了一次大规模的装修.原来的地板铺有 N×M 块正方形瓷砖,这些瓷砖都已经破损老

hiho #1044 : 状态压缩&#183;一

描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市——那座城市即将举行美食节! 但是不幸的是,小Hi和小Ho并没有能够买到很好的火车票——他们只能够乘坐最为破旧的火车进行他们的旅程. 不仅如此,因为美食节的吸引,许多人纷纷踏上了和小Hi小Ho一样的旅程,于是有相当多的人遭遇到了和小Hi小Ho一样的情况——这导致这辆车上的人非常非常的多,以至于都没有足够的位置能让每一个人都有地方坐下来. 小Hi和小Ho本着礼让他们的心情——当然还因为本

hoj 2662 状态压缩dp

题意: 给定mxn的棋盘,要往其中放d枚棋子,其中,一枚棋子的上下左右四个位置不能再放棋子.求所有合法的放置状态 ( 0<m,n<=80 , mxn<=80 ) 棋盘位置可多达80,爆搜目测超时,我用的状态压缩dp. 棋盘中的一个格子,放棋用1,不放用0 压缩其中一维,每个状态数用一个二进制数表示. 每个状态都是棋盘一行的放置方法 假设,m >= n , 这个递推棋盘就有 m行 ,每行至多有 2^n-1个状态数.其实,没有这么多!按照题意,每个1的上下左右不能有1.对于一行,只知左