L型骨牌覆盖问题。

问题:解决一个2k*2k的特殊棋牌上的L型骨牌覆盖问题。

思路:

棋盘覆盖实现的基本方法为分治法

当k=0时(1ⅹ1棋盘),及特殊方格,骨牌数为0

当k >0时,将2kⅹ2k棋盘分割为4个2k-1ⅹ2k-1子棋盘了

特殊方格位于4个较小子棋盘之一中,而其余3个子棋盘中无特殊方格。

在递归之前要将原问题转化为4个较小规模的相同子问题。(用一个L型骨牌覆盖这3个子棋盘的会合处)

这三个子棋盘上被L型骨牌覆盖的方格就成为该棋盘上的特殊方格,从而将问题分解为4个较小规模的棋盘覆盖问题。

递归地使用这种分割方法,直至棋盘简化为1ⅹ1棋盘,就结束递归。

具体实现

对每个子棋盘按照左上,右上,右下,左下的顺时针顺序铺满棋盘。(顺序不一样,铺出来的编号也不一样)

    每次都对分割后的四个小方块进行判断,判断特殊方格是否在里面。

如果特殊方块在里面,这直接递归下去即可,

    如果不在,这根据分割的四个方块的不同位置,把右下角、左下角、左上角、右上角的方格标记为特殊方块,然后继续递归。

    在递归函数里,还要有一个变量h来记录边的方格数,每次对方块进行划分时,边的方格数都会减半,这个变量是为了方便判断特殊方格的位置。

代码实现

x:棋盘左上角方格的行号

y:棋盘左上角方格的列号

a:特殊方格的行号

b:特殊方格的列号

length:2k,棋盘规模:2kⅹ2k

源码:

#include<iostream>

#include<iomanip> 

using namespace std;

int matrix[100][100];

int num = 0;

void chessBoard(int x, int y, int a, int b, int length);



int main()

{

    int a, b, length;

    cout << "请输入棋盘的行列号";

    cin >> length;

    cout << "请输入特殊方格的行列号";

    cin >> a >> b;

    matrix[a][b] = 0;



    chessBoard(1, 1, a, b, length);



    for (int i = 1; i <= length; i++) {

         for (int j = 1; j <= length; j++) {

             cout << setw(4) << matrix[i][j];

         }

         cout << endl;

    }

    system("pause");

    return 0;

}

void chessBoard(int x, int y, int a, int b, int length) {

   

    if (length == 1) {

         return;

    }

    int h = length / 2;  

    int t = ++num;       

    /*左上角*/

    if (a < x + h && b < y + h) { 

         chessBoard(x, y, a, b, h);

    }

    else {  

         matrix[x + h - 1][y + h - 1] = t;

         chessBoard(x, y, x + h - 1, y + h - 1, h);

    }

    /*右上角*/

    if (a < x + h && b >= y + h) { 

         chessBoard(x, y + h, a, b, h);

    }

    else { 

         matrix[x + h - 1][y + h] = t;

         chessBoard(x, y + h, x + h - 1, y + h, h);

    }

    /*右下角*/

    if (a >= x + h && b >= y + h) { 

         chessBoard(x + h, y + h, a, b, h);

    }

    else { 

         matrix[x + h][y + h] = t;

         chessBoard(x + h, y + h, x + h, y + h, h);

    }

    /*左下角*/

    if (a >= x + h && b < y + h) { 

         chessBoard(x + h, y, a, b, h);

    }

    else {  

         matrix[x + h][y + h - 1] = t;

         chessBoard(x + h, y, x + h, y + h - 1, h);

    }

}

运行截图:

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先,我们可以将特殊棋盘分成4个相等的部分,分别考虑每个部分的覆盖情况。由于每个L骨牌覆盖3个方格,而特殊方格无法被覆盖,因此每个部分中必定有一个空位,使得无法被覆盖。我们可以将这个空位标记为特殊点,并且要求特殊点必须在L骨牌的中心位置上。 接下来考虑如何覆盖每个部分。我们可以将每个部分看作一个2×2的小棋盘,其中必定有一个特殊点。对于每个小棋盘,我们可以选择放置一个L骨牌,使得它覆盖特殊点以外的所有方格。这样做的前提是特殊点所在的行和列中必须有一条直线可以被覆盖,否则无法放置L骨牌。由于每个小棋盘都是相互独立的,因此我们只需要考虑一种小棋盘的覆盖方法。 假设小棋盘的特殊点在左上角,那么我们只有2种情况可以将它覆盖:一种是放置一个横向的L骨牌,另一种是放置一个竖向的L骨牌。对于横向的L骨牌,它必须覆盖特殊点所在的行和下面一行,同时覆盖右边两列的任意一个方格;对于竖向的L骨牌,它必须覆盖特殊点所在的列和右边一列,同时覆盖下面两行的任意一个方格。 综上所述,我们可以先判断特殊点所在的行和列是否满足条件,如果满足则分别考虑横向和竖向的L骨牌是否可以放置,如果都不行则无解。如果存在解,则我们可以采用递归的方式,将整个棋盘分成4个部分,分别求解每个部分的覆盖方案。最后将4个部分的方案合并起来即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五敷有你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值