棋盘覆盖
问题描述
- 在一个2^k×2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。显然特殊方格在棋盘上出现的位置有4的k次方种,要用以下四种L行的方块将其完全覆盖,且不得有方块重复覆盖
解题思路:
分析:此题可以用分治策略进行算法设计,当k>0时,我们可以将
2^k-1*2^k-1 棋盘分割成2^k×2^k 的子棋盘,特殊方格每次位于4个较小棋盘之一,而且我们可以发现,在无特殊方格的子棋盘中,中心点的临近方格就是L行骨牌的汇合处,即无特殊方格的子棋盘的中心点汇合处,就是L行的骨牌所在位置,所以我们可以每次判断特殊方块的位置,并将无特殊方块的子棋盘的父棋盘中心点汇合处标上,在进行下一次分割,直至棋盘无法分割
实现:
#include<stdio.h>
#include<string.h>
int title=1;
int Border[100][100];
void ChessBoard(int tr,int tc,int dr,int dc,int sizet);
void print(){
printf("****************************\n");
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
printf("%d ",Border[i][j]);
}
printf("\n");
}
printf("\n**********************\n");
}
int main(){
memset(Border,0,sizeof(Border));
Border[0][1]=0;
ChessBoard(0,0,0,1,4);
print();
}
void ChessBoard(int tr,int tc,int dr,int dc,int size){
if(size==1) return ;//棋盘无法分割
int t= title++;//用于在当前中心点会和处标记L形骨牌
int s=size/2;//下一次分割的规模
//判断特殊方格是否在左上子棋盘中
if(dr<tr+s&&dc<tc+s){
//如果特殊方格在此子棋盘中,继续分割;
ChessBoard(tr,tc,dr,dc,s);
print();
}else{
//无特殊方格,将右下角标为特殊方格 ,即为L形骨牌的三分之一
Border[tr+s-1][tc+s-1]=t;
ChessBoard(tr,tc,tr+s-1,tc+s-1,s);print();
}
//判断特殊方格是否在 左下角的子棋盘中
if(dr>=tr+s&&dc<tc+s){
//特殊方格在此子棋盘中 ,继续分割
ChessBoard(tr+s,tc,dr,dc,s); print();
} else{
//无特殊方格,将右上角标为特殊方格 , 即为L形骨牌的三分之一
Border[tr+s][tc+s-1]=t;
ChessBoard(tr+s,tc,tr+s,tc+s-1,s);print();
}
//右上角
if(dr<tr+s&&dc>=tc+s){
ChessBoard(tr,tc+s,dr,dc,s);print();
}else{
Border[tr+s-1][tc+s]=t;
ChessBoard(tr,tc+s,tr+s-1,tc+s,s);print();
}
//右下角
if(dr>=tr+s&&dc>=tc+s){
ChessBoard(tr+s,tc+s,dr,dc,s);print();
}else{
Border[tr+s][tc+s]=t;
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);print();
}
}
这里我用print()将标记过程动态化
tr:棋盘左上角行号
tc:期盼左上角列号
dr:特殊方格行号
dc:特殊方格列号
size:棋盘规格
title:全局变量,用来标识L形骨牌
border[][]:棋盘
这里请大家注意对方格进行数字的表示,
Border[tr+s][tc+s-1]=t;
这里是最后的结果显示,代码已经亲测过