棋盘覆盖问题

本文介绍了一种解决特殊棋盘覆盖问题的分治策略,通过递归地将大问题分解为小问题来求解。具体而言,作者提出了一种将棋盘分割并使用L型牌覆盖白色方块的方法,确保不覆盖黑色方块且每个白色方块仅被一个牌覆盖。通过将棋盘不断分割和覆盖,最终实现整个棋盘的覆盖目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       有一个有2^k×2^k个方格的棋盘,恰有一个方格是黑色的,其他为白色。你的任务是用包含3个方格的L型牌覆盖所有白色方格。黑色方格不能被覆盖,且任意一个白色方格不能同时被两个或更多牌覆盖。如图(1)所示为L型牌的四种旋转方式。
     下图–图(1)中的特殊棋盘是当k=3时16个特殊棋盘中的一个:
                                          

图(1)

输入格式:

第一行含有三个数据:分别为n(<=50 <=0 保证是4的倍数):棋盘边长,x(<=n >=1):特殊方格横坐标,y(<=n >=1):特殊方格纵坐标。


输入样例:

8 5 6


输出样例:

  4  4  5  5  9  9 10 10
  4  2  2  5  9  7  7 10
  6  2  0  3  8  8  7 11
  6  6  3  3  1  8 11 11
 14 14 13  1  1 18 19 19
 14 12 13 13 18 18 17 19
 15 12 12 16 20 17 17 21
 15 15 16 16 20 20 21 21




本题解题思路:

图为样例输入

先将棋盘分割成四个子棋盘,再将没有特殊方格的子棋盘的靠近分割点的三格覆盖骨牌。
       将子棋盘再分割成四个更小的子棋盘,并按照之前的方法,将黄色格子当做特殊格子,实现分治,将没有特殊方格的子棋盘的靠近中心分割点的三格覆盖骨牌。
子棋盘为2×2时填充剩下的格子便完成了。

代码如下:
#include<cstdio>
using namespace std;
int x,y,n,i,j,t=0; 
//x:特殊格子横坐标 y:特殊格子纵坐标 n:棋盘边长 i,j:循环变量 t:当前骨牌编号 
int map[51][51]; 
//本程序使用递归实现分治. 
void CB(int x,int y,int m,int n,int s)
//x:棋盘左上角横坐标 y:棋盘左上角纵坐标 m:特殊格子横坐标 n:特殊格子纵坐标 s:棋盘边长 
{
	int sa,temp;//sa:子棋盘边长  temp:交换临时变量 
	if(s==2)//递归边界:子棋盘边长=2 
	{
		temp=map[m][n];//先将四个格子全部覆盖,再将原来的特殊格子重新填充 
		map[x][y]=t+1; 
		map[x][y+1]=t+1;
		map[x+1][y]=t+1;
		map[x+1][y+1]=t+1;
		map[m][n]=temp;
		t++;
		return;
	} 
	t++; 
	sa=s/2;
	if(m<x+sa && n<y+sa) //特殊格子在左上角 
	{
		map[x+sa-1][y+sa]=t;//摆放骨牌 
		map[x+sa][y+sa-1]=t;
		map[x+sa][y+sa]=t;
		CB(x,y,m,n,sa);//递归调用子棋盘 
		CB(x,y+sa,x+sa-1,y+sa,sa);
		CB(x+sa,y,x+sa,y+sa-1,sa);
		CB(x+sa,y+sa,x+sa,y+sa,sa);
	}
	if(m<x+sa && n>=y+sa) //特殊格子在右上角
	{
		map[x+sa-1][y+sa-1]=t;//摆放骨牌
		map[x+sa][y+sa-1]=t;
		map[x+sa][y+sa]=t;
		CB(x,y+sa,m,n,sa);//递归调用子棋盘 
		CB(x,y,x+sa-1,y+sa-1,sa);
		CB(x+sa,y,x+sa,y+sa-1,sa);
		CB(x+sa,y+sa,x+sa,y+sa,sa);
	}
	if(m>=x+sa && n<y+sa) //特殊格子在左下角
	{
		map[x+sa-1][y+sa-1]=t;//摆放骨牌
		map[x+sa-1][y+sa]=t;
		map[x+sa][y+sa]=t;
		CB(x+sa,y,m,n,sa);//递归调用子棋盘 
		CB(x,y,x+sa-1,y+sa-1,sa);
		CB(x,y+sa,x+sa-1,y+sa,sa);
		CB(x+sa,y+sa,x+sa,y+sa,sa);
	}
	if(m>=x+sa && n>=y+sa) //特殊格子在右下角
	{
		map[x+sa-1][y+sa-1]=t;//摆放骨牌
		map[x+sa-1][y+sa]=t;
		map[x+sa][y+sa-1]=t;
		CB(x+sa,y+sa,m,n,sa);//递归调用子棋盘 
		CB(x,y,x+sa-1,y+sa-1,sa);
		CB(x,y+sa,x+sa-1,y+sa,sa);
		CB(x+sa,y,x+sa,y+sa-1,sa);
	}
	

}
int main()
{
	scanf("%d%d%d",&n,&x,&y);//n:棋盘边长 x:特殊格子横坐标 y:特殊格子纵坐标
	CB(1,1,x,y,n);//调用递归 
	for(i=1;i<=n;i++)//循环输出结果 
	{
		for(j=1;j<=n;j++) printf("%3d",map[i][j]);
		printf("\n");
	}
	return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值