分治算法-棋盘覆盖

棋盘覆盖问题)在一个 2k×2k 个方格组成的棋盘中恰有一个方格与其它方格不同(图中标记为 −1 的方格),称之为特殊方格。现 L 型(占 3 个小方格)纸片覆盖棋盘上除特殊方格的所有部分,各纸片不得重叠,于是,用到的纸片数恰好是 (4k−1)/3​。在下表给出的一个覆盖方案中,k=2,相同的 3 各数字构成一个纸片。下面给出的程序使用分治法设计的,将棋盘一分为四,依次处理左上角、右上角、左下角、右下角,递归进行。请将程序补充完整。

代码实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**************************************************************** 
 * 代码作者: Alex Li
 * 创建时间: 2023-04-24 18:05:38
 * 最后修改: 2026-05-01 09:38:30
 * 文件描述: 分治  棋盘覆盖
****************************************************************/

#include <iostream>
#include <iomanip>
using namespace std;
int board[65][65], tile; /* tile 用于给每个 L 型骨牌编号 */

// 递归覆盖 chessboard:在 row/column 为左上角、size 为边长的棋盘中,
// 让 (x, y) 这个特殊方格不被覆盖,其余区域全部用 L 型骨牌铺满。
void chessboard( int row, int column, int x, int y, int size ){
	int t, s;

	if ( size == 1 ) return;// 递归终止:1×1 棋盘无需再铺
	t = ++tile;// 当前这层递归分配一个新的骨牌编号
	s = size / 2;

	
	if ( x < row + s && y < column + s )// 左上象限:如果特殊方格不在这里,就用当前骨牌补上这个象限的中心格
		chessboard( row, column, x, y, s );
	else{
		board[row + s - 1][column + s - 1] = t;
		chessboard( row, column, row + s - 1, column + s - 1, s );
    }

	if ( x < row + s && y >= column + s )// 右上象限:如果特殊方格不在这里,就用当前骨牌补上这个象限的中心格
		chessboard( row, column + s, x, y, s );
	else{
		board[row + s - 1][column + s] = t;
		chessboard( row, column + s, row + s - 1, column + s, s );
	}

	if ( x >= row + s && y < column + s )	// 左下象限
		chessboard( row + s, column, x, y, s );
	else{
		board[row + s][column + s - 1] = t;
		chessboard( row + s, column, row + s, column + s - 1, s );
	}

	
	if ( x >= row + s && y >= column + s )// 右下象限
		chessboard( row + s, column + s, x, y, s );
	else{ 
        board[row + s][column + s] = t;
	      chessboard( row + s, column + s, row + s, column + s, s );
    }
}


void princolumnhessboard( int b[][65], int n )
{
	int i, j;
	for ( i =1; i <= n; i++ )
	{
		for ( j =1; j <= n; j++ )
			cout << setw( 3 ) << b[i][j];
			// setw(3) output three characters field width.
		cout << endl;
	}
}


int main(){
	int size, x, y;
	cout << "input size(4/8/16/64):" << endl;
	cin >> size;
	cout << "input the position of special block(x,y):" << endl;
	cin >> x >> y;
	board[x][y] = -1;
	
	chessboard( 1, 1, x, y, size );
	princolumnhessboard( board, size );
}

洛谷:P1911
OJ: Y3440/P1352