首页 > 代码库 > 算法重拾之路——棋盘覆盖

算法重拾之路——棋盘覆盖

***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************


隶属于递归与分治


棋盘覆盖问题


问题描述: 

在一个2^k × 2^k个方格组成的棋盘中,若恰有一个方格与其他方格不同,则该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,用下图所示四种‘ L ‘型骨牌覆盖一个给定的特殊棋盘中除特殊方格之外的所有方格,而且任意两个‘L‘型骨牌不可重叠覆盖。(而且知道了,在任何一个2^k × 2^k 的棋盘覆盖中,用到的L型骨牌个数恰为 (4^k-1)/ 3 个。

 



问题解法: 该问题用到分治策略来解决,

当 k > 0 时, 将 2^k × 2^k 棋盘分割成 4 个 2^(k-1) × 2^(k-1) 子棋盘,如下图:


特殊的方格,必定位于这四个小子棋盘中的一个,其余三个棋盘中没有特殊方格。

为了将剩余三个子棋盘也用‘L‘型骨牌 覆盖,所以在每个棋盘中 设置一个 方格为特殊方格,

可以发现,这三个方格正好可以组成一个‘L‘型骨牌,如下图:


这样,就可以递归下去,直至棋盘规模为1×1。



算法代码:

<span style="font-family:Comic Sans MS;font-size:14px;">void CheseBoard( int lr , int lc , int sr , int sc , int _size )
{
    if( _size == 1 )    return;
    int t = tile++ , s = _size/2;

    // 判断特殊格子是否在四个区域中左上角区域
    if( sr < lr + s && sc < lc + s )
        CheseBoard(lr,lc,sr,sc,s);
    else    {
        Board[lr+s-1][lc+s-1]=t;
        CheseBoard(lr,lc,lr+s-1,lc+s-1,s);
    }

    // 判断特殊格子是否在四个区域中右上角区域
    if( sr < lr + s && sc >= lc + s )
        CheseBoard(lr,lc+s,sr,sc,s);
    else    {
        Board[lr+s-1][lc+s]=t;
        CheseBoard(lr,lc+s,lr+s-1,lc+s,s);
    }

    // 判断特殊格子是否在四个区域中左下角区域
    if( sr >= lr + s && sc < lc + s )
        CheseBoard(lr+s,lc,sr,sc,s);
    else    {
        Board[lr+s][lc+s-1]=t;
        CheseBoard(lr+s,lc,lr+s,lc+s-1,s);
    }

    // 判断特殊格子是否在四个区域中右下角区域
    if( sr >= lr + s && sc >= lc + s )
        CheseBoard(lr+s,lc+s,sr,sc,s);
    else    {
        Board[lr+s][lc+s]=t;
        CheseBoard(lr+s,lc+s,lr+s,lc+s,s);
    }
}</span>

应该不需要解释很多了,单纯的说一下各参数意思吧:

lr,lc     左上角的横、纵坐标

sr,sc   特殊格子的横、纵坐标

_size   棋盘的规模(棋盘要2^k)



算法分析:

设T(k) 是算法CheseBoard覆盖一个2^k×2^k棋盘所需要的时间,从算法的分治策略可以求出:

T(k)= O(1) 当k=0时

=4*T(k-1)+O(1)当k>0时

这个递归方程解出可得 T(k) = O(4^k) 。



***************************************转载请注明出处:http://blog.csdn.net/lttree********************************************


算法重拾之路——棋盘覆盖