1.问题描述:在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方格,如何覆盖。四个L型骨牌如下图:
棋盘中的特殊方格如图:
2.设计思路:设计思路:采用二分法把棋盘分为不同的部分,如图中的4*4,分为4个2*2的棋盘;判断特殊方格在哪一个棋盘中,然后用一个骨牌填充其他没有特殊方格的棋盘,这样每一个棋盘中都有一个‘特殊’的方格,把每一个小问题都变成独立的解;依次递归,直到棋盘中只剩下一个方格退出递归函数;
3.代码:
/*二分法解决棋盘覆盖问题*/
#include<stdio.h>
#define N 4
int chess[N][N]; //定义棋盘,棋盘的大小应该为2的k次方
int tiel=1; //定义骨牌编号
void ChessBoard(int tr,int tc,int dr,int dc,int size)//tr,tc为开始的横纵坐标;dr,dc为特殊方格的横纵坐标;size为棋盘的大小
{
if(size==1) //棋盘中只剩下一个方格的时候结束递归
{
return ;
}
int count=tiel++;
size=size/2;
//printf("%d \n",count);
if(dr<tr+size&&dc<tc+size) //如果特殊方格在左上棋盘就在此棋盘上递归
{
ChessBoard(tr,tc,dr,dc,size);
}
else{ //该部分的棋盘没有特殊方格
chess[tr+size-1][tc+size-1]=count; //给该部分的棋盘放置方格
ChessBoard(tr,tc,tr+size-1,tc+size-1,size); //覆盖该部分棋盘的剩余位置
}
if(dr<tr+size&&dc>=tc+size) //如果特殊方格在右上棋盘就在此棋盘上递归
{
ChessBoard(tr,tc+size,dr,dc,size);
}
else{ //该部分的棋盘没有特殊方格
chess[tr+size-1][tc+size]=count; //给该部分的棋盘放置方格
ChessBoard(tr,tc+size,tr+size-1,tc+size,size); //覆盖该部分棋盘的剩余位置
}
if(dr>=tr+size&&dc<tc+size) //如果特殊方格在左下棋盘就在此棋盘上递归
{
ChessBoard(tr,tc,dr,dc,size);
}
else{ //覆盖该部分棋盘的剩下部分
chess[tr+size][tc+size-1]=count;
ChessBoard(tr+size,tc,tr+size,tc+size-1,size);
}
if(dr>=tr+size&&dc>=tc+size) //如果特殊方格在右下棋盘就在此棋盘上递归
{
ChessBoard(tr+size,tc+size,dr,dc,size);
}
else{ //覆盖该部分棋盘的剩下部分
chess[tr+size][tc+size]=count;
ChessBoard(tr+size,tc+size,tr+size,tc+size,size);
}
}
int main()
{
chess[2][2]=0;
ChessBoard(0,0,2,2,N);
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
printf("%d ",chess[i][j]);
}
printf("\n");
}
return 0;
}
4.运行结果:
5.总结:
二分法的关键是分而治之。通过将棋盘的均分,然后递归求解,最终得到问题的解。