首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

木块砌墙

  • 25-03-02 17:21
  • 3114
  • 11065
blog.csdn.net

木块砌墙

用如下3种木块砌墙。


木块如上,不能翻转,墙如下图:

 

 

问有多少种方法。n<=1024  k<=4,答案对1000000007取余。

 

分析:

            首先,因为木块的宽度都是1,我们可以想成2维的问题。也就是说三种木板的规格分别为1* 1, 1 * 2, 2 * 1。

            看到这个问题最直接的想法就是暴力搜索。对每个空格尝试放置哪种木板。但是看看数据规模就知道,这种思路是不可行的。因为有一条边范围长度高达21024,普通的电脑,230左右就到极限了。于是我们猜测别的方法。

            为了方便,我们把墙看做有2n行,k列的矩形。这是因为虽然矩形木块不能翻转,但是我们同时拥有1*2和2*1的两种木块。

假设我们从上到下,从左到右考虑每个1*1的格子是如何被覆盖的。显然,我们每个格子都要被覆盖住。木块的特点决定了我们覆盖一个格子最多只会影响到下一行的格子。这就可以让我们暂时只考虑两行。假设现我们已经完全覆盖了前(i– 1)行。那么由于覆盖前(i-1)行导致第i行也不“完整”了。如下图:我们用x表示已经覆盖的格子,o表示没覆盖的格子。为了方便,我们使用9列。


xxxxxxxxx

ooxooxoxo

 

我们考虑第i行的状态,假设如上图。第1列我们可以用1*1的覆盖掉,也可以用1*2的覆盖前两列。第3,4列的覆盖方式和第12列是同样地情况。第7列需要覆盖也有两种方式,即用1*1的覆盖或者用2*1的覆盖,但是这样会导致第(i+1)行第7列也被覆盖。第9列和第7列的情况是一样的。这样把第i行覆盖满了之后,我们再根据第(i+1)行被影响的状态对下一行进行覆盖。

            那么每行有多少种状态呢?显然有2k,由于k很小,我们只有大约16种状态。如果我们对于这些状态之间的转换制作一个矩阵,矩阵的第i行第j列的数表示的是我们第m行是状态i,我们把它完整覆盖掉,并且使得第(m + 1)行变成状态j的可能的方法数,这个矩阵我们可以暴力搜索出来,搜索的方式就是枚举第m行的状态,然后尝试放木板,用所有的方法把第m行覆盖掉之后,下一行的状态。这里,其实我们可以认为只有两行,并且第一行是2k种状态的一种,第二行起初是空白的,求使得第一行完全覆盖掉,第二行的状态有多少种类型以及每种出现多少次。

            这个矩阵作用很大,其实我们覆盖的过程可以认为是这样:第一行是空的,我们看看把它覆盖了,第2行是什么样子的。根据第二行的状态,我们把它覆盖掉,看看第3行是什么样子的。

            如果我们知道第i行的状态为s,怎么考虑第i行完全覆盖后,第(i+1)行的状态?那只要看那个矩阵的状态s对应的行就可以了。我们可以考虑一下,把两个这样的方阵相乘得到得结果是什么。这个方阵的第i行第j个元素是这样得到的,是第i行第k个元素与第k行第j个元素的对k的叠加。它的意义是上一行是第m行是状态i,把第m行和第(m+ 1)行同时覆盖住,第(m+2)行的状态是j的方法数。这是因为中间第(m+1)行的所有状态k,我们已经完全遍历了。

            于是我们发现,每做一次方阵的乘法,我们相当于把状态推动了一行。那么我们要坐多少次方阵乘法呢?就是题目中墙的长度2n,这个数太大了。但是事实上,我们可以不断地平方n次。也就是说我们可以算出A2,A4, A8, A16……方法就是不断用结果和自己相乘,这样乘n次就可以了。

        因此,我们最关键的问题就是建立矩阵A。我们可以这样表示一行的状态,从左到右分别叫做第0列,第1列……覆盖了我们认为是1,没覆盖我们认为是0,这样一行的状态可以表示维一个整数。某一列的状态我们可以用为运算来表示。例如,状态x第i列是否被覆盖,我们只需要判断x & (1 << i) 是否非0即可,或者判断(x >> i) & 1, 用右移位的目的是防止溢出,但是本题不需要考虑溢出,因为k很小。 接下来的任务就是递归尝试放置方案了。

 

            最终结果,我们最初的行是空得,要求最后一行之后也不能被覆盖,所以最终结果是矩阵的第[0][0]位置的元素。另外,本题在乘法过程中会超出32位int的表示范围,需要临时用C/C++的long long,或者java的long。



  1. #ifdef WIN32
  2. #define ll __int64
  3. #else
  4. #define ll long long
  5. #endif
  6. // 1 covered 0 uncovered
  7. void cal(int a[6][32][32],int n,int col,int laststate,int nowstate) {
  8. if (col >= n) {
  9. ++a[n][laststate][nowstate];
  10. return;
  11. }
  12. //不填 或者用1*1的填
  13. cal(a,n, col + 1, laststate, nowstate);
  14. if (((laststate >> col) & 1) == 0) {
  15. cal(a,n, col + 1, laststate, nowstate | (1 << col));
  16. if ((col + 1 < n) && (((laststate >> (col + 1)) & 1) == 0)) {
  17. cal(a,n, col + 2, laststate, nowstate);
  18. }
  19. }
  20. }
  21. inline int mul(ll x, ll y) {
  22. return x * y % 1000000007;
  23. }
  24. void multiply(int n,int a[][32],int b[][32]) { // b = a * a
  25. int i,j, k;
  26. for (i = 0; i < n; ++i) {
  27. for (j = 0; j < n; ++j) {
  28. for (k = b[i][j] = 0; k < n; ++k) {
  29. if ((b[i][j] += mul(a[i][k],a[k][j])) >= 1000000007) {
  30. b[i][j] -= 1000000007;
  31. }
  32. }
  33. }
  34. }
  35. }
  36. int calculate(int n,int k) {
  37. int i, j;
  38. int a[6][32][32],mat[2][32][32];
  39. memset(a,0,sizeof(a));
  40. for (i = 1; i <= 5; ++i) {
  41. for (j = (1 << i) - 1; j >= 0; --j) {
  42. cal(a,i, 0, j, 0);
  43. }
  44. }
  45. memcpy(mat[0], a[k],sizeof(mat[0]));
  46. k = (1 << k);
  47. for (i = 0; n; --n) {
  48. multiply(k, mat[i], mat[i ^ 1]);
  49. i ^= 1;
  50. }
  51. return mat[i][0][0];
  52. }




    

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览49583 人正在系统学习中
注:本文转载自blog.csdn.net的cpcs的文章"http://blog.csdn.net/caopengcs/article/details/9928061"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top