解题报告 Diamonds

1. 题目 diamonds 题目描述 小keke同学非常喜欢玩俄罗斯方块(*^*),他最近发现传统的俄罗斯方块很无趣,于是他想到了一个新规则的游戏来恶心你(……,没素质啊)。 游戏是这样的: 给定你一个宽度为w的游戏场地,我们设高度为正无穷。现在给你3种俄罗斯方块: 1*2的方块 2*2的方块 2*2的方块去掉一个1*1的方块 如果你明白俄罗斯方块的规则的话,方块在下落过程中是可以随便旋转的。而且是从上往下落,上面的落在下面的上面(废话!!!) 现在给定你一个高度h,让你求出有多少种游戏的方法,使得最后恰好落满h的高度(最上层是齐平的)。因为这样可以得巨多分!巨!舒服~~~~~ 输入文件(diamonds.in) 两个整数h,w含义如题所述 输出文件(diamonds.out) 一个整数,为能达到要求的游戏方法的总数。 数据范围 1<=h,w<=9,注意答案有可能很大(你懂得,用不到高精度) 样例输入 2 2 样例输出 3 2. 题目实质 用给定的三种砖讲一个区域铺满(又是废话) 3. 算法 DP+DFS (也就是状态压缩型 DP ) 首先,每一个状态均可以由他前面的某一个状态转移而来,所以,满足 DP 的无后效性,用 DP 解决。 方程十分好写:f[I,j]:=sigma(f[I-1,k]*g[k,j](其中状态 k 可以转移到状态 j ,I 表示该状态铺满的高度为高度为 I )) 初始值 f[1,0]:=1; 因为本题中一共三种砖,所以情况会很多,这也是比较恶心人的地方,因为情况太多,有多种转移的方法,所以不能用 Boolean 类型数组直接判断,而应该用一个 g 数组记录,然后用乘法原理,将方案数直接进行累加。 状态用二进制(HASH)存储。 将矩阵的1行看成一种状态,则某一行矩阵的铺砖情况可以用一个01串表示:0表示未铺砖,1表示已铺了砖。 然后,状态改变时用位运算改变。 对于上下两行:要能用某种类型的砖铺,必须该砖所覆盖的区域为空。 当搜出边界时,直接跳出。(递归出口) 4. 注意事项 一定要开 int64 ! 5. 程序代码 Leve (pascal) var n,m,i,j,k:longint; f:array[0..9,0..1024] of int64; g:array[0..1024,0..1024] of int64; procedure dfs(step,now:longint); begin if step=m+1 then begin inc(g[i,now]); exit; end; if 1<<(step-1) and i<>0 then dfs(step+1,now) //如果这一行不能再铺了,就搜下一行。 else begin if (1<1) then dfs(step+1,now+1<<(step-1)+1<<(step-2)); end; //铺 2*2-1*1 end; end; begin assign(input,'diamonds.in'); assign(output,'diamonds.out'); reset(input); rewrite(output); readln(n,m); for i:=0 to 1<
原文地址:https://www.cnblogs.com/SueMiller/p/2133801.html