2k*2k 棋盘覆盖问题

棋盘覆盖问题

  1. 问题叙述
    在一个2k×2k个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

图示:
在这里插入图片描述
实例:
在这里插入图片描述
2. 基本思路:
关注的重点是特殊方格,2k2k的棋盘上如果没有特殊点,那么L型骨牌不可能完全覆盖,那么我们分治的思路是,每一个父棋盘分解为4个相同大小的子棋盘,除了本身就有特殊点的一个子棋盘,为另外三个棋盘人工设置3个特殊点,以此满足递归条件;基本情况是11棋盘,直接返回。

  1. 算法
//tr,tc为当前棋盘的左上角行号列号,dr,dc为特殊点行号列号,size是大小
CHSEEBOARD (tr, tc, dr, dc, size):
	if size==1 return
//tile是一个全局变量,它不满足递归,用于对人工设置的三个特殊点标记相同的数字
	t=++tile
//左上角
	if dr<tr+s && dc<tc+s
		CHESSBOARD (tr, tc, dr, dc, s)
	else
		board[tr+s-1][tc+s-1] = t;
		CHESSBOARD (tr, tc, tr+s-1, tc+s-1, 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, 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+s, dr, dc, s)
	else
		board[tr+s-1][tc+s-1] = t;
		CHESSBOARD (tr+s, tc+s, tr+s, tc+s, s);

  1. 复杂度:O(n^2)
    T(1)=1
    T(n)=4T(n/2)+1
    =>T(n)=O(n^2)

  2. 运行截图
    8*8棋盘
    在这里插入图片描述

  3. 源代码

#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;

int tile = 0;
void chessBoard(vector<vector<int>> & board,int tr, int tc, int dr, int dc, int size)
{
	if(size==1)	return;
	int t = ++tile;
	int s = size/2;
	//左上 
	if(dr<tr+s && dc<tc+s)
		chessBoard(board,tr,tc,dr,dc,s);
	else
	{
		board[tr+s-1][tc+s-1] = t;
		chessBoard(board,tr,tc,tr+s-1,tc+s-1,s);
	}
	//左下 
	if(dr>=tr+s && dc<tc+s)
		chessBoard(board,tr+s,tc,dr,dc,s);
	else
	{
		board[tr+s][tc+s-1] = t;
		chessBoard(board,tr+s,tc,tr+s,tc+s-1,s);
	}
	//右上 
	if(dr<tr+s && dc>=tc+s)
		chessBoard(board,tr,tc+s,dr,dc,s);
	else
	{
		board[tr+s-1][tc+s] = t;
		chessBoard(board,tr,tc+s,tr+s-1,tc+s,s);
	}
	//右下 
	if(dr>=tr+s && dc>=tc+s)
		chessBoard(board,tr+s,tc+s,dr,dc,s);
	else
	{
		board[tr+s][tc+s] = t;
		chessBoard(board,tr+s,tc+s,tr+s,tc+s,s);
	}
}

void Print(const vector<vector<int>> &board)
{
	int n= board.size();
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			cout<<setw(2)<<left<<board[i][j]<<" ";
		}
		cout<<endl;
	}
}

int main(int argc, char** argv) {
	vector<vector<int>> board;
	board.resize(8);
	for(int i=0;i<board.size();i++)
	{
		board[i].resize(8);
	}
	board[3][3] = 0;
	chessBoard(board,0,0,3,3,board.size());
	Print(board);	
	return 0;
}

注:文章中的示例及L型骨牌图片来自于
https://blog.csdn.net/yew1eb/article/details/8776985

### 回答1: 题目要求解决的问题是如何摆放2k×2k棋盘,使得其一个方格与其他方格不同,称为特殊方格。现在要用如下的L型骨牌覆盖除了特殊方格外的所有方格,骨牌的大小为2×2。现在要摆放特殊方格使得骨牌能覆盖所有的方格,而且任何两个骨牌不能覆盖特殊方格。因为特殊方格被称为特殊,所以骨牌摆放的方案是特殊的。如果使用L型骨牌不能完成这个任务,那么任何两个骨牌都不能摆放在特殊方格周围。 ### 回答2: 分治法是一种将问题分解成若干个子问题来解决复杂问题的算法。棋盘覆盖问题就可以使用分治法来求解。 首先我们把2k×2k棋盘分成4个小的棋盘,每个小棋盘的大小为k×k。接着找到特殊方格所在的小棋盘,这个小棋盘会被分成四个小的棋盘。 然后我们需要对每个小棋盘进行递归处理。如果当前的小棋盘不包含特殊方格,那么我们可以使用3个不同的L型骨牌来覆盖。如果当前的小棋盘包含特殊方格,那么我们需要选一个位置来放置一个L型骨牌来覆盖这个特殊方格,并把小棋盘继续分解。如果有特殊方格的小棋盘被分成四个小的棋盘,那么这四个小的棋盘必须有一个特殊方格。否则,我们就无法使用L型骨牌来完全覆盖这个小棋盘。 在递归处理完所有的小棋盘后,我们就可以成功地覆盖了整个棋盘。这个算法的时间复杂度为O(k^2),因为每个小棋盘都需要被处理一次。 总之,分治法是一种非常有效的求解复杂问题的算法,适用于许多不同的领域。在棋盘覆盖问题,我们可以将棋盘分成小的棋盘,然后递归地解决每个小棋盘。这种方法非常简单、高效,能够在较短的时间内求解出问题。 ### 回答3: 棋盘覆盖问题是计算机科学一个经典问题,可以使用分治法求解。该问题要求用L型骨牌覆盖大小为2^k×2^k的棋盘,其一个格子被标记为特殊方格,不能被覆盖。解决该问题需要将棋盘分成四个大小相等的子棋盘,然后分别求解每个子棋盘的覆盖问题,最后将子棋盘覆盖方案合并成整个棋盘的覆盖方案。 下面介绍分治法求解棋盘覆盖问题的具体步骤: 1.递归边界条件:当棋盘大小为1时,问题得到解决。 2.将棋盘分成四块:首先找到特殊方格所在的子棋盘所处的象限,然后将棋盘分成四块,其特殊方格所在的子棋盘所处的象限保留为空,其他子棋盘用L型骨牌覆盖。 3.递归求解:对于每个子棋盘,递归求解棋盘覆盖问题,直至棋盘大小为1。 4.合并解:将每个子棋盘的覆盖方案合并成整个棋盘的覆盖方案。 需要注意的是,在分割棋盘时,特殊方格的位置可能会发生变化,因此需要记录特殊方格的位置并在合并解时进行调整。 分治法求解棋盘覆盖问题的时间复杂度为O(4^k),其k为棋盘的大小,因此该算法在棋盘大小较小时具有较高的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值