棋盘覆盖

题意:有一个2^n*2^n的棋盘,在棋盘上面有一个特殊的方块,在此棋盘上面使用L型的骨牌进行覆盖,而且不能覆盖特殊的方块而且任意的骨牌也不能重叠,问应该怎么用L型的骨牌覆盖此棋盘?

棋盘:

这是一个棋盘,红色的为特殊的方格,我们要用如下的四种L型骨牌覆盖此棋盘:

L型骨牌:

 

思路:使用分治法对棋盘进行覆盖,首先把棋盘划分成四个部分,那么特殊的方格一定位于四个小的棋盘中的某一个。分别对四个小的棋盘进行覆盖,由于分治法处理的是划分成相同的情况,而特殊的方格只有一个且位于某一个小的棋盘中,我们需要把另外的三个棋盘都拿一个方格来作为特殊的方格,由此想出把拿出的三个格子组成一个L型骨牌,这样就满足了每个小的棋盘都一个

特殊的方格,而且拿出来的特殊方格形成一个L型的骨牌。然后对四个小的棋盘分而治之,直到方格数为1就停止!表明已经到达了最小的问题了。

a图是一个原始的棋盘,把大的棋盘划分成四个更小的棋盘,b图红色的代表原来的特殊的方格,而三个黄色的方格是没有特殊方格的棋盘拿出来的,在中间的位置刚好组成一个L型的骨牌。

代码:

#include <iostream>
#include<cmath> 
#include<algorithm>
const int maxn = 500;
using namespace std;
int board[maxn][maxn],index = 0;//棋盘数组//指示L型棋盘的索引 
//参数解析:
//tr(棋盘左上角方格的行号),tc(棋盘左上角方格的列号),dr(特殊方格的行号),dc(特殊方格的列号),size(棋盘大小) 
void chessBoard(int tr,int tc,int dr,int dc,int size){
	if(size == 1){//只有一个方格了,最小问题,直接返回 
		return; 
	} 
	int t = ++index,s = size/2;
	
	if(dr<tr+s && dc<tc+s){//如果特殊方块在棋盘的左上角的区域 
		chessBoard(tr,tc,dr,dc,s);//继续递归把此大的方块划分为更小的方块 
	}else{//如果不在左上角 
		board[tr+s-1][tc+s-1] = t;//将左上角那一部分的有下角那个方块置t,此方块为人为构造一个L型骨牌 
		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] = t;
		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] = t;
		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] = t;
		chessBoard(tr+s,tc+s,tr+s,tc+s,s);
	} 
}
void print(int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			printf("%d%s",board[i][j],j==n-1?"\n":" ");
		}
	}
}
int main(int argc, char** argv) {
	int n = 0,row,col; 
	printf("请输入棋盘大小n:(棋盘的规模为(2*n)*(2*n))\n");
	scanf("%d",&n);
	int size = (int)pow(2,n);
	printf("请输入特殊的方格坐标:\n");
	scanf("%d%d",&row,&col);//输入特殊方格的坐标
	chessBoard(0,0,row,col,size);
	print(size);//打印棋盘 
	return 0;
}

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值