首页 > 代码库 > 算法重拾之路——棋盘覆盖
算法重拾之路——棋盘覆盖
***************************************转载请注明出处: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********************************************
算法重拾之路——棋盘覆盖