题目详情

用 1×1×1, 1× 2×1以及2×1×1的三种木块,

搭建K × 2^N × 1的墙,不能翻转、旋转(0<=N<=1024,1<=K<=5)

有多少种方案,输出结果对1000000007取模。

举例:

举个例子如给定N=1 K=2

答案是7,如下图所示

答题说明
main函数可以不实现,完成给定的子函数calculate即可(之所以给出main,在于方便你在线编译测试)
==================================================================================================================================
首先,我们把墙倒过来放,即K在下边,这样得到的结果会和原来的墙一模一样,原因很明显就不证了,倒过来是为了降低时间复杂度。
思路:
每一层有一个状态值,该值起决于下一层有那几个位置放了2*1*1的木块。
比如一层有5个位置(倒过来后,K在下边,K最大为5)  第x-1层 只有第1,3位置放了 2*1*1的木块,那么第x层的状态就可以表示为10100既20、显然每层可能的状态值就是0到2^k-1
一旦某一层的状态值确定了(也就是该层有那几个位置被下一层占了),就可以根据这个状态值,搜出所有该状态值下的放木块的方法,而每一种方法,又确定了上一层的状态值。
由此:
我们设 F(x, y)  为从上往下x行, 且x行的状态值为y的总的摆放方案  
比如F(2,1)   表示从上往下数2行(既包含第1行和第2行),且第2行的第一个位置(10000)被第3行占了的情况了 可以摆放的方案数。
状态转移式:
F(x, y) =  F(x-1, h(1)) + F(x-1, h(2)) + F(x-1, h(3)) + ......+F(x-1,h(g(y)));
其中g(y) 表示一行中,状态值是y时,该行所有摆放的方案数
每个h都是表示一种该层的摆放方式所确定的上一层的值。比如改行在第1,3位置摆了2*1*1,其他都摆放了1*1*1,那么上一层的状态值就是20
答案就是F(2*n, 0);
特殊情况:
当最顶上一层的状态值为2^k-1时,该层的摆放方案是0。
在最顶上一层的上边有个虚拟层,该层所有状态值下的F都为1.(便于计算的)
代码:
[cpp] view plaincopyprint?
  1. #include <cstdio>
  2. #include <string>
  3. #include <cstring>
  4. using namespace std;
  5. #ifdef WIN32
  6. #define ll __int64
  7. #else
  8. #define ll long long
  9. #endif
  10. int stan = 0,stak= 0;
  11. ll f[3000][1<<6];
  12. //将二进制转成十进制
  13. ll bit2int(int bit[], int k)
  14. {
  15. ll i=1;
  16. ll ans = bit[0];
  17. for (i = 1; i < k ;i++)
  18. ans += bit[i] * (1<<i);
  19. return ans;
  20. }
  21. //十进制转成2进制
  22. void int2bit(int bit[], ll num)
  23. {
  24. memset(bit,0,sizeof(bit));
  25. ll i;
  26. for (i = 0; num != 0 ; i++)
  27. {
  28. bit[i] = num % 2;
  29. num/=2;
  30. }
  31. }
  32. ll all = 0;
  33. //计算从上往下到第x行(包含上边所有行) 以x状态为y 时 的每种一种放法特例所得到的f(x-1,h),加到all上去
  34. void count(ll x,int bit[],ll n,int bit2[]);
  35. //计算从上往下到第x行(包含上边所有行) 以x状态为y 时的方法总数
  36. int dp(ll x,ll y)
  37. {
  38. if (x == 1 && y == (1<<stak )-1) return 0;
  39. if (x == 0) return 1;
  40. if (f[x][y] != 0) return f[x][y];//已经计算过了
  41. all = 0;
  42. //第x行的2进制表示
  43. int bit[6];
  44. int2bit(bit,y);
  45. //第x-1行的2进制表示
  46. int bit2[6];
  47. memset(bit2,0,sizeof(bit2));
  48. //计算
  49. count(x,bit,0,bit2);
  50. return (f[x][y] = all);
  51. }
  52. //第x行,从第0到n位的都放过了
  53. void count(ll x,int bit[],ll n,int bit2[])
  54. {
  55. //递归边界
  56. if (n>=stak)
  57. {
  58. //将得到的bit2[]转成状态h,就可以得到f(x-1,h). 加到 all上面去
  59. all = (all + dp(x-1,bit2int(bit2,stak)))  % 1000000007 ;
  60. return ;
  61. }
  62. //这位被占了,那么这位不能放东西,且x-1的这位,必然是0
  63. if (bit[n] == 1)
  64. {
  65. bit2[n]=0;
  66. count(x,bit,n+1,bit2);
  67. }
  68. //如果这位是空的,那么3种方块都有可能放
  69. else
  70. {
  71. //放1*1*1
  72. bit2[n] = 0;
  73. count(x,bit,n+1,bit2);
  74. //放2*1*1
  75. bit2[n] = 1;
  76. count(x,bit,n+1,bit2);
  77. //放1*2*2 条件是这一位置不是最后一位,且下一位置可以放
  78. if (n<stak && bit[n+1] == 0 )
  79. {
  80. bit2[n] = 0;
  81. bit2[n+1] = 0;
  82. count(x,bit,n+2,bit2);
  83. }
  84. }
  85. }
  86. int calculate(int n,int k)
  87. {
  88. stak = k;
  89. stan = n;
  90. memset(f,0,sizeof(f));
  91. return dp(2*n,0);
  92. }
  93. //start 提示:自动阅卷起始唯一标识,请勿删除或增加。
  94. int main() {
  95. //自行定义n,k
  96. int n,k;
  97. //为了调试,实际提交要去掉这行
  98. while(1)
  99. {
  100. scanf("%d%d",&n, &k);
  101. printf("%d\n",calculate(n,k));
  102. }
  103. return 0;
  104. }
  105. //end //提示:自动阅卷结束唯一标识,请勿删除或增加。
结束语:
这题有种直觉,可以更简单。。没多考虑,直接这么写了。。。有更好方法的朋友,留个言!

木块砌墙---解题报告相关推荐

  1. 通过木块砌墙题目体会动态规划算法

    木块砌墙题目: 用三种木块,搭建k×2n×1的墙,不能翻转.旋转木块(0≤ n≤ 1024 ,1 ≤ k ≤ 5),计算有多少种方案,输出结果对1000000007取模. 图1 木块与墙 该题目是在庞 ...

  2. 第三十三章:木块砌墙

    题目:用 1×1×1, 1× 2×1以及2×1×1的三种木块(横绿竖蓝,且绿蓝长度均为2), 搭建高长宽分别为K × 2^N × 1的墙,不能翻转.旋转(其中,0<=N<=1024,1&l ...

  3. 最小操作数,木块砌墙问题

    第三十二章.最小操作数 题目详情如下: 给定一个单词集合Dict,其中每个单词的长度都相同.现从此单词集合Dict中抽取两个单词A.B,我们希望通过若干次操作把单词A变成单词B,每次操作可以改变单词的 ...

  4. 木块砌墙算法(C#源码)

    木块砌墙算法(C#版) 首先感谢 网友"⒌1→⑤Ⅵ℡" 提供算法讲解和其他网友提供的帮助. 原题链接:http://hero.pongo.cn/Question/Details?I ...

  5. 程序员编程艺术第三十二~三十三章:最小操作数,木块砌墙问题

    第三十二~三十三章:最小操作数,木块砌墙问题 作者:July.caopengcs.红色标记.致谢:fuwutu.demo. 时间:二零一三年八月十二日 题记 再过一两月,便又到了每年的九月十月校招高峰 ...

  6. CF197D Infinite Maze 解题报告

    CF197D Infinite Maze 解题报告 1 题目链接 原题 2 题目翻译 题目:无限的迷宫 题目描述 现在有一个 n × m n\times m n×m的一个长方形迷宫.其中每个单元格要么 ...

  7. 2022.2.18解题报告

    2022.2.18解题报告 T1.切蛋糕 题目描述: 思路: 首先,我们先来看一下最少用几刀就可以解决所有情况. 对于一个蛋糕,要分成至少三块,那么最少都要2刀,因为0刀或1刀分出的蛋糕数量都小于3. ...

  8. CF225D Snake 解题报告 *

    CF225D Snake 解题报告 1 题目链接 https://codeforces.com/problemset/problem/225/D 2 题目整理 题目 : 蛇 题目描述 让我们提醒你一个 ...

  9. 连飞学长的爱 解题报告 Apare_xzc

    连飞学长的爱 解题报告 2019/2/22 vj链接 A-A CodeForces - 560A 题意: 有一套纸币,有n个币种,问是否能构成任意面值? input: n a1 a2 - an 数据范 ...

最新文章

  1. web标准化设计:常用的CSS命名规则
  2. 初学Python常见异常错误,总有一处你会遇到!
  3. docker之Dockerfile实践
  4. 双边滤波器在灰度和彩色图像处理中的应用
  5. servlet多线程
  6. python处理大文件_Python如何处理大文件(知识整理)
  7. 记一次服务器本地Tomcat能访问,但远程访问不了的解决方案
  8. 【Hadoop】MapReduce
  9. 对JavaScript解析JSON格式数据的理解
  10. kettle使用_ETL工具(kettle)使用系列(二)
  11. day1 java基础回顾- 文件路径
  12. 数据结构最短路径例题_数据结构(五)图---最短路径(迪杰斯特拉算法)
  13. 计算机软件技术发展应用论文,计算机软件毕业论文计算机软件技术发展应用.docx...
  14. 用迅雷下载百度网盘的文件
  15. numpy矩阵与向量类型的向量乘法
  16. office显示“你的许可证并非正版....”
  17. 怎么用python编简单游戏大全_适合新手练手的三个python简单小游戏
  18. 通过冥想解除困意,提升精神
  19. JavaScript:在一段时间不连续的数据中获取某一段时间段内相同时间间隔的数据
  20. 寂寂的流年,时光日渐青翠

热门文章

  1. 计算机系统维护与管理论文,探讨计算机系统的管理与维护的论文
  2. 装载问题——优先队列
  3. 淘宝新手每天要做些什么
  4. 七个案例,读博读废了是种什么样的体验?
  5. 回溯算法在点菜中的应用例子
  6. 软件开发团队常见角色职责【转】
  7. Codevs 抄书问题123
  8. Windows Server入门系列32 利用SamInside获取系统密码Hash值
  9. 120年过去,历史不该忘记
  10. 正则表达式替换全部 中文汉字 英文 数字