棋盘覆盖

棋盘覆盖

问题描述

  1. 在一个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;


这里是最后的结果显示,代码已经亲测过

猜你喜欢

转载自blog.csdn.net/m0_37687058/article/details/79743707