棋盘覆盖问题是一个经典的分治问题的算法,它其中的思想,就是分而治之。
怎么体现分而治之的思想是这个问题的关键。
首先,将棋盘分为四个小的方块,体现了分,但是却破坏了问题的统一性,因为小的方块中,三个块中没有特殊的方块。
所以为了不破坏分而不乱的思想,我们可以在每一个小块中加一个特殊的小方块,但是加一个小方块,随便填的话,同样还是破坏了分的目的,故,书本上给出了一种比较高明的技巧,在没有特殊块的方块中,将一个L型的块放到三个块的交界处,一来,这是一种往棋盘填块的方式,不破坏题意的目的,二来,又增加了其他三个无特殊块的方格,三个特殊方格。可谓是一举两得,这样使得分开之后的问题与原问题是一样的,只有这样才可以用分治法来处理。
下面上代码同样的,使用了c++代码
//棋盘覆盖 #include<iostream> #include<cstring> #include<cstdlib> #define SIZE 8 using namespace std; int Board[SIZE][SIZE];//棋盘坐标 int kind; //放置牌的种类 void ChessBoard(int tr,int tc,int dr,int dc,int size){ if(size==1)return; int t=kind++; int s=size/2; // 从左上角的方块开始检查 if(dr < tr + s&&dc < tc + s)//特殊块在该区域,就直接递归 ChessBoard(tr,tc,dr,dc,s); else{ //特殊块不在该区域,则在右下角放一小块然后递归 Board[tr+s-1][tc+s-1]=t; ChessBoard(tr,tc,tr+s-1,tc+s-1,s); } //检查右上角的大方块 if(dr < tr + s&&dc >= tc + s)//同上 ChessBoard(tr,tc+s,dr,dc,s); else{ Board[tr+s-1][tc+s]=t; ChessBoard(tr,tc+s,tr+s-1,tc+s,s); } //检查左下角的大方块 if(dr >= tr + s&&dc < tc + s) ChessBoard(tr+s,tc,dr,dc,s); else{ Board[tr+s][tc+s-1]=t; ChessBoard(tr+s,tc,tr+s,tc+s-1,s); } //检查右下角的大方块 if(dr >= tr + s&&dc >= tc + s) ChessBoard(tr+s,tc+s,dr,dc,s); else{ Board[tr+s][tc+s]=t; ChessBoard(tr+s,tc+s,tr+s,tc+s,s); } } int main(){ memset(Board,0,sizeof(Board));//棋盘初始化为0 cout<<"Initnation the Board!The curent sutation is:"<<endl; for(int i = 0;i < SIZE;i ++){ for(int j = 0;j < SIZE;j ++) cout<<Board[i][j]<<" "; cout<<endl; } //打印当前的棋盘状态 cout<<"The chessboard is covered..."<<endl; ChessBoard(0,0,0,3,SIZE); //开始放置 cout<<"The chessboard is:"<<endl; cout.fill('0'); //用0填充空白 for(int i = 0;i < SIZE;i ++){ for(int j = 0;j < SIZE;j ++){ cout.width(2); //便于查看控制字符为两个空白的宽度 cout<<Board[i][j]<<" "; } cout<<endl; } system("pause"); }