跳至主要內容

棋盘覆盖问题

路九阳2024年11月15日大约 3 分钟教学文档递归

题目描述

在一个 2k*2k 个方格组成的棋盘中,若恰有一个方格与其他方格不同,则称该方格为特殊方格,且称该棋盘为一特殊棋盘。用4种不同的L型骨牌覆盖一个给定的特殊棋盘(即特殊方格的位置已经确定了)上除去特殊方格外的所有方格,并且任何两个L型骨牌不得重复覆盖。

图 0
图 0

输入格式:

  • 第一行输入一个整数N,代表棋盘规模(N为2的k次幂)
  • 第二行输入两个整数x、y,代表特殊方格的行号、列号。其中,x、y均从0开始

输出格式:

  • 一个二维数组,以矩阵的形式输出,表示棋盘的覆盖情况。

输入样例:

棋盘规模: 8 行号、列号: 3 4

输出样例:

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

解题思路

当 K > 0 时,可以将 2k*2k的棋盘划分为4个 2(k-1)*2(k-1)的子棋盘。这样划分后,由于原棋盘只有一个特殊方格,所以这4个子棋盘中只有1个子棋盘中有特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化为特殊棋盘,以便采用递归方法求解,可以用一个L型骨牌覆盖这3个较小的棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为 1*1 的子棋盘。

代码实现

#include<iostream>
#include<vector>
using namespace std;
vector <vector <int>> A(100,vector<int>(100,0));
int t = 0;
void chessBoard(int tr,int tc,int dr,int dc,int size){
	if(size == 1) return ;
	int s = size / 2;
	int x = ++t;		//在每一层递归调用上都为同一个值,且一定会在三个象限上各出现一次,递归每深入一层x+1
	//第一象限
	if((dr < tr + s)&&(dc < tc + s)){//如果特殊方格位于该区域,则在该区域内递归调用该函数
		chessBoard(tr,tc,dr,dc,s);
	}else{
		//否则覆盖该区域的右下角方格(此方格在递归的意义上也成为特殊方格)
		A[tr + s - 1][tc + s -1] = x;
		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{
		A[tr + s - 1][tc + s] = x;
		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{
		A[tr + s][tc + s] = x;
		chessBoard(tr + s,tc + s,tr + s,tc + s - 1,s);
	}
	//第四象限
	if((dr >= tr + s)&&(dc < tc + s)){
			chessBoard(tr + s,tc,dr,dc,s);
	}else{
			A[tr + s][tc + s - 1] = x;
			chessBoard(tr + s,tc,tr + s,tc + s - 1,s);
	}
	return;
}
int main(){
	int n;
	cout<<"棋盘规模:"<<endl;
	cin >> n;
	if (((n & (n-1)) != 0)||(n == 0)){
		cout << "非法值"<<endl;
		exit(-1);
	}
	int i,j;
	cout<<"行号、列号:"<<endl;
	cin >> i >> j;
	if((i > n)||(j > n)){
			cout << "非法值"<<endl;
				exit(-1);
	}
	A[i][j] = -1;
	cout<<"----------------------------------"<<endl;
	chessBoard(0,0,i,j,n);
	for(int i = 0;i < n;i++){
	        for(int j = 0;j < n;j++){
				cout << A[i][j]<<" "; 
			}		
			cout << endl;
		}
	return 0;
}
上次编辑于: 2025/1/13 09:18:24
贡献者: molittle,zilizhou