二分法之棋盘覆盖问题

1.问题描述:在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方格,如何覆盖。四个L型骨牌如下图:

棋盘中的特殊方格如图:

2.设计思路:设计思路:采用二分法把棋盘分为不同的部分,如图中的4*4,分为4个2*2的棋盘;判断特殊方格在哪一个棋盘中,然后用一个骨牌填充其他没有特殊方格的棋盘,这样每一个棋盘中都有一个‘特殊’的方格,把每一个小问题都变成独立的解;依次递归,直到棋盘中只剩下一个方格退出递归函数;

3.代码:

/*二分法解决棋盘覆盖问题*/ 
#include<stdio.h>
#define N 4
int chess[N][N];	//定义棋盘,棋盘的大小应该为2的k次方 
int tiel=1;		//定义骨牌编号 
void ChessBoard(int tr,int tc,int dr,int dc,int size)//tr,tc为开始的横纵坐标;dr,dc为特殊方格的横纵坐标;size为棋盘的大小 
{
	if(size==1)			//棋盘中只剩下一个方格的时候结束递归 
	{
		return ;
	}
	 int count=tiel++;
	 size=size/2;
	 //printf("%d \n",count);
	if(dr<tr+size&&dc<tc+size)			//如果特殊方格在左上棋盘就在此棋盘上递归 
	{
		ChessBoard(tr,tc,dr,dc,size); 
	}
	else{													//该部分的棋盘没有特殊方格 
		chess[tr+size-1][tc+size-1]=count;					//给该部分的棋盘放置方格 
		ChessBoard(tr,tc,tr+size-1,tc+size-1,size);			//覆盖该部分棋盘的剩余位置 
	}
	if(dr<tr+size&&dc>=tc+size)		 //如果特殊方格在右上棋盘就在此棋盘上递归 
	{
		ChessBoard(tr,tc+size,dr,dc,size); 
	 } 
	 else{													//该部分的棋盘没有特殊方格
	 	chess[tr+size-1][tc+size]=count;		   			//给该部分的棋盘放置方格
	 	ChessBoard(tr,tc+size,tr+size-1,tc+size,size);		//覆盖该部分棋盘的剩余位置
	 }
	 if(dr>=tr+size&&dc<tc+size)		//如果特殊方格在左下棋盘就在此棋盘上递归
	 {
	 	ChessBoard(tr,tc,dr,dc,size);
	 }
	 else{                                 //覆盖该部分棋盘的剩下部分 
	 	chess[tr+size][tc+size-1]=count;
	 	ChessBoard(tr+size,tc,tr+size,tc+size-1,size);
	 }
	 if(dr>=tr+size&&dc>=tc+size)			//如果特殊方格在右下棋盘就在此棋盘上递归
	 {
	 	ChessBoard(tr+size,tc+size,dr,dc,size);
	 }
	 else{									//覆盖该部分棋盘的剩下部分 
	 	chess[tr+size][tc+size]=count;
	 	ChessBoard(tr+size,tc+size,tr+size,tc+size,size);
	 }
 }
int main()
{
	chess[2][2]=0;
	ChessBoard(0,0,2,2,N);	
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			printf("%d  ",chess[i][j]);
		}
		printf("\n");
	}	
	return 0;		
 } 

 4.运行结果:

5.总结:

二分法的关键是分而治之。通过将棋盘的均分,然后递归求解,最终得到问题的解。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值