Description
在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
Input
输入一个整数k,k<=5;
输入特殊格子的坐标x,y。
Output
输出一个由数值表示的二维矩阵。填充规则如下:
(1)用数值填充方格;
(2)特殊方格数值为0;
(3)从中心点开始;然后左上、右上、左下、右下的计数顺序填数;同一块用相同数值表示;
(4)每个数值占4个位置空间;右对齐,左补空格。
分析:
函数的主干是四个if else循环,也就是说只会执行一个if中的语句,但是会执行3个else中的语句,这3个else中的语句就是构造不可覆盖格子,然后对含有新构造的不可覆盖点的子棋盘来重写进行棋盘覆盖,也就是递归调用棋盘覆盖函数,递归的结束条件就是子棋盘只有一个格子,也就是s=1,每次调用棋盘覆盖函数,都要进行s=size/2,目的就是把一个大棋盘划分为四个相同大小的子棋盘。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int number=0;
int Board[33][33];
//tr,tc是方格左上角的位置,dr,dc是特殊方格的位置
void ChessBoard(int tr,int tc,int dr,int dc,int size)
{
if(size==1)
return;
int ind=++number;//骨牌的编号
int s=size/2;//将棋盘分割为4个子问题,即行和列各取一半
if(dr<tr+s && dc<tc+s)//当特殊格子在左上的子问题中
ChessBoard(tr,tc,dr,dc,s);
else//如果特殊格子不在左上时,将左上的右下角标记为黑格
{
Board[tr+s-1][tc+s-1]=ind;//用编号为ind的骨牌覆盖该子问题中的右下角
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]=ind;
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]=ind;
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]=ind;
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
int main()
{
int k,x,y;
scanf("%d",&k);
int size=pow(2,k);
scanf("%d%d",&x,&y);
ChessBoard(0,0,x,y,size);
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
printf("%4d",Board[i][j]);
}
printf("\n");
}
return 0;
}