《计算机算法设计与分析》第三版递归与分治章节中有一类棋盘覆盖问题。
在一个2^k * 2^k个方格组成的棋盘中,若恰好有一个方格与其他方格不同,则称该方格为一个特殊方格,显然在特殊方格在棋盘上出现的为止有4^k种情形。因而对任何k>=0,有4^k种不同的特殊棋盘。
有上图四种不同形态的L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。易知在任何一个2^k * 2^k的棋盘覆盖中,用到的L型骨牌个数恰好为(4^k – 1)/3。
实现的基本原理是将2^k * 2^k的棋盘分成四块2^(k – 1) * 2^(k – 1)的子棋盘,特殊方格一定在其中的一个子棋盘中,如果特殊方格在某一个子棋盘中,继续递归处理这个子棋盘,直到这个子棋盘中只有一个方格为止如果特殊方 格不在某一个子棋盘中,将这个子棋盘中的相应的位置设为骨牌号,将这个无特殊方格的了棋盘转换为有特殊方格的子棋盘,然后再递归处理这个子棋盘。
以下是实现的源代码,可能递归起来比较复杂,我在上面做了详细的注释,可以设置八个断点,根据断点一步一步进行调试就行了。
#include <iostream>
#include <string>
using namespace std;
int board[32][32];
//tr,tc每个被分方格的左上角那个
//dr,dc每个被分方格的特殊位置
//刚开始方格的特殊位置
void chessBoard(int tr,int tc,int dr,int dc,int size)
{
if( size == 1 )
return ;
int half_size ;
static int num=1;
int t=num++;
half_size = size /2 ;
//left up
if( dr<tr+half_size && dc < tc+half_size ) //特殊方格在左上角子棋盘
chessBoard(tr, tc, dr, dc, half_size); //如果在左上方,则不需要改变tr,tc起始点的为止0 ,0 。设置短点
else
{ //设置断点
board[tr+half_size-1][tc+half_size-1]=t;
chessBoard(tr, tc, tr+half_size-1, tc+half_size-1, half_size);
}
//right up //特殊方格在右上角子棋盘
if( dr<tr+half_size && dc>=tc+half_size )
chessBoard(tr, tc+half_size, dr, dc, half_size); //如果在右上方则需要改变tr,tc的位置,移动到tr,tc+half_size。 设置短点
else // 不在此棋盘,将此棋盘右下角设为相应的骨牌号
{ //设置断点
board[tr+half_size-1][tc+half_size] = t;
chessBoard(tr, tc+half_size, tr+half_size-1, tc+half_size, half_size); //tr,tc的位置也要同时改变
}
//left down
if( dr>=tr+half_size && dc<tc+half_size )
chessBoard(tr+half_size, tc, dr, dc, half_size); //设置断点
else
{
board[tr+half_size][tc+half_size-1] = t; //设置短点
chessBoard(tr+half_size, tc, tr+half_size, tc+half_size-1, half_size); //tr,tc的位置也要同时改变
}
//right down
if(dr>=tr+half_size && dc>=tc+half_size )
chessBoard(tr+half_size, tc+half_size, dr, dc, half_size); //设置短点
else
{
board[tr+half_size][tc+half_size] = t; //设置短点
chessBoard(tr+half_size, tc+half_size, tr+half_size, tc+half_size, half_size); //tr,tc的位置也要同时改变
}
}
int main()
{
int size;
cout<<"输入方格的大小,必须是2的n的幂"<<endl;
cin>>size;
int x,y;
cout<<"输入特殊方格的位置:"<<endl;
cin>>x>>y;
memset(board,0,sizeof( board[size][size]) );
chessBoard(0,0,x,y,size);
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
cout<<board[i][j]<<" ";
cout<<endl;
}
return 1;
}
下面是结果截图,可以用这个简单的数据进行调试: