hackenzheng

   日期:2024-12-26    作者:n1p0t 移动:http://ljhr2012.riyuangf.com/mobile/quote/46708.html

hackenzheng

枚举摆放的这一步可以采用dfs递归枚举列,递归出口为列数col == N时。dfs函数的原型可以写成如下的形式:
       void dfs( int col, int nextrow, int nowstate, int nextstate, LL cnt);
       // col       表示当前枚举到的列编号
       // nextrow   表示下一行的行编号
       // nowstate  表示当前枚举骨牌摆放时第i  行的状态(随着放置骨后会更新)
       // nextstate 表示当前枚举骨牌摆放时第i+1行的状态(随着放置骨后会更新)
       // cnt       状态转移前的方案数,即第i行在放置骨牌前的方案数
       然后再来看如何将骨牌摆上去,这里对骨牌进行归类,旋转之后得到如下六种情况:
图二-4-6
图二-4-7
       为了方便叙述,分别给每个类型的骨牌强加了一个奇怪的名字,都是按照它自身的形状来命名的,o(╯□╰)o。然后我们发现它们都被圈定在一个2X2的格子里,所以每个骨牌都可以用2个2位的2进制整数来表示,编码方式类似上面的状态表示法(参照图6,如果骨牌对应格子为蓝色则累加格子上的权值),定义如下:
 
int blockMask[6][2] = {
     {1, 1},    // 竖向2X1
     {3, 0},    // 横向1X2
     {3, 1},    // 枪
     {3, 2},    // 7
     {1, 3},    // L
     {2, 3},    // J
};
       blockMask[k][0]表示骨牌第一行的状态,blockMask[k][1]表示骨牌第二行的状态。这样一来就可以通过简单的位运算来判断第k块骨牌是否可以放在(i, col)这个格子上,这里的i表示行编号,col则表示列编号。接下来需要用到位运算进行状态转移,所以先介绍几种常用的位运算:
       a. x & (1<<i)   值如果非0,表示x这个数字的二进制表示的第i(i >= 0)位为1,否则为0;
       b. x & (y<<i)   值如果非0,表示存在一个p(i <= p < i+k),使得x这个数字的二进制表示的第p位和y的p-i位均为1(k为y的二进制表示的位数);
       c. x | (1<<i)   将x的第i位变成1(当然,有可能原本就为1,这个不影响);
       d. x | (y<<i)   将x的第i~i+k-1位和y进行位或运算(k为y的二进制表示的位数),这一步就是模拟了骨牌摆放
       那么这个格子可以放置第k个骨牌的条件有如下几个:
       1、当前骨牌横向长度记为w,那么w必须满足 col + w <= N,否则就超出右边界了。
       2、 nowstate (blockMask[k][0]<<col)  == 0,即第i行,骨牌放入前对应的格子为空(对应的格子表示骨牌占据的格子,下同)
       3、nextstate (blockMask[k][1]<<col)  == 0,即第i+1行,骨牌放入前对应的格子为空
       4、最容易忽略的一点是,“J”骨牌放置时,它的缺口部分之前必须要被骨牌铺满,否则就无法满足第i行全铺满这个条件了,如图二-4-8所示的情况。
图二-4-8
 
       当四个条件都满足就可以递归进入下一层了,递归的时候也是采用位运算,实现如下:
       dfs( col+1, nextrow, nowstate|(blockMask[k][0]<<col), nextstate|(blockMask[k][1]<<col), cnt );
       这里的位或运算(|)就是模拟将一个骨牌摆放到指定位置的操作(参见位运算d)。
       当然,在枚举到第col列的时候,有可能(i, col)这个格子已经被上一行的骨牌给“占据”了(是否被占据可以通过 (1<<col) & nowstate 得到),这时候我们只需要继续递归下一层,只递增col,其它量都不变即可,这表示了这个格子什么都不放的情况。

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


举报收藏 0评论 0
0相关评论
相关最新动态
推荐最新动态
点击排行
{
网站首页  |  关于我们  |  联系方式  |  使用协议  |  隐私政策  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号