在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方格,如何覆盖。
四各L型骨牌如下图1
图1
棋盘中的特殊方格如图2
图2
实现的基本原理是将2^k * 2^k的棋盘分成四块2^(k - 1) * 2^(k - 1)的子棋盘,特殊方格一定在其中的一个子棋盘中,如果特殊方格在某一个子棋盘中,继续递归处理这个子棋盘,直到这个子棋盘中只有一个方格为止如果特殊方格不在某一个子棋盘中,将这个子棋盘中的相应的位置设为骨牌号,将这个无特殊方格的了棋盘转换为有特殊方格的子棋盘,然后再递归处理这个子棋盘。以上原理如图3所示。
图3
将棋盘保存在一个二维数组中。骨牌号从1开始,特殊方格为0,如果是一个4 * 4的棋盘,特殊方格为(2,2),那么程序的输出为
2 2 3 3
2 1 1 3
4 1 0 5
4 4 5 5
相同数字的为同一骨牌。
下面是棋盘覆盖问题的c语言实现。
/*
实现的基本原理是将2^k * 2^k的棋盘分成四块2^(k - 1) * 2^(k - 1)的子棋盘,
特殊方格一定在其中的一个子棋盘中,如果特殊方格在某一个子棋盘中,
继续递归处理这个子棋盘,直到这个子棋盘中只有一个方格为止如果特殊方格不在某一个子棋盘中,
将这个子棋盘中的相应的位置设为骨牌号,将这个无特殊方格的了棋盘转换为有特殊方格的子棋盘,
然后再递归处理这个子棋盘。*/
#include<stdio.h>
#include<string.h>
#define N 70
int block[N][N];
static int level;
void find(int r1,int c1,int r2,int c2,int size0)
{
int d,size;
if(size0==1) return ;
size=size0/2;
d=level++;
if(r2<r1+size&&c2<c1+size)//特殊块在左上角
find(r1,c1,r2,c2,size);
else//不在左上角
{
block[r1+size-1][c1+size-1]=d;
find(r1,c1,r1+size-1,c1+size-1,size);
}
if(r2<r1+size&&c2>=c1+size)//特殊块在右上角
find(r1,c1+size,r2,c2,size);
else//不在右上角
{
block[r1+size-1][c1+size]=d;
find(r1,c1+size,r1+size-1,c1+size,size);
}
if(r2>=r1+size&&c2<c1+size)//特殊块在左下角
find(r1+size,c1,r2,c2,size);
else//不在左下角
{
block[r1+size][c1+size-1]=d;
find(r1+size,c1,r1+size,c1+size-1,size);
}
if(r2>=r1+size&&c2>=c1+size)//特殊块在右下角
find(r1+size,c1+size,r2,c2,size);
else//不在右下角
{
block[r1+size][c1+size]=d;
find(r1+size,c1+size,r1+size,c1+size,size);
}
}
int main()
{
int i,j,n,T,a,b,k;
scanf("%d",&T);
for(k=1;k<=T;k++)
{
scanf("%d",&n);
scanf("%d %d",&a,&b);
block[a][b]=0;
//memset(block,0,sizeof(block));
level=1;
find(0,0,a,b,n);
printf("CASE:%d\n",k);
for(i=0;i<n;i++)
{
printf("%d",block[i][0]);
for(j=1;j<n;j++)
printf("\t%d",block[i][j]);
printf("\n");
}
}
return 0;
}