棋盘覆盖
问题描述
- 在一个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;
这里是最后的结果显示,代码已经亲测过