棋盘覆盖问题是一个经典的分治问题的算法,它其中的思想,就是分而治之。
怎么体现分而治之的思想是这个问题的关键。
首先,将棋盘分为四个小的方块,体现了分,但是却破坏了问题的统一性,因为小的方块中,三个块中没有特殊的方块。
所以为了不破坏分而不乱的思想,我们可以在每一个小块中加一个特殊的小方块,但是加一个小方块,随便填的话,同样还是破坏了分的目的,故,书本上给出了一种比较高明的技巧,在没有特殊块的方块中,将一个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");
}