文章目录
- @[toc]
- 问题描述
- 分治算法
- 时间复杂性
- `Python`实现
文章目录
- @[toc]
- 问题描述
- 分治算法
- 时间复杂性
- `Python`实现
个人主页:丷从心·
系列专栏:分治算法
学习指南:Python学习指南
问题描述
- 在一个 2 k × 2 k 2^{k} \times 2^{k} 2k×2k个方格组成的棋盘中,若恰有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一特殊棋盘
- 用 4 4 4种不同形态的 L L L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何 2 2 2个 L L L型骨牌不得重复覆盖
分治算法
- 当 k > 0 k > 0 k>0时,将 2 k × 2 k 2^{k} \times 2^{k} 2k×2k棋盘分割为 4 4 4个 2 k − 1 × 2 k − 1 2^{k - 1} \times 2^{k - 1} 2k−1×2k−1子棋盘,特殊方格必位于 4 4 4个较小子棋盘之一中,其余 3 3 3个子棋盘中无特殊方格
- 为了将这 3 3 3个无特殊方格的子棋盘转化为特殊棋盘,可以用一个 L L L型骨牌覆盖这 3 3 3个较小棋盘的会合处
时间复杂性
T ( k ) = { O ( 1 ) k = 0 4 T ( k − 1 ) + O ( 1 ) k > 0 T(k) = \begin{cases} O(1) & k = 0 \\ 4 T(k - 1) + O(1) & k > 0 \end{cases} T(k)={O(1)4T(k−1)+O(1)k=0k>0
T ( k ) = O ( 4 k ) T(k) = O(4^{k}) T(k)=O(4k)
- 由于覆盖一个 2 k × 2 k 2^{k} \times 2^{k} 2k×2k棋盘所需的 L L L型骨牌个数为 ( 4 k − 1 ) / 3 (4^{k} - 1) / 3 (4k−1)/3,故算法是一个在渐进意义下最优的算法
Python
实现
def chessboard_cover(board, tr, tc, dr, dc, size):
"""
:param board: 棋盘
:param tr: 棋盘左上角行号
:param tc: 棋盘左上角列号
:param dr: 特殊方格行号
:param dc: 特殊方格列号
:param size: 棋盘大小
"""
global tile_count
# 基本情况: 棋盘大小为 1, 直接放置骨牌
if size == 1:
return
t = tile_count
tile_count += 1
# 将棋盘分成 4 个子棋盘
s = size // 2
# 左上子棋盘
if dr < tr + s and dc < tc + s:
chessboard_cover(board, tr, tc, dr, dc, s)
else:
board[tr + s - 1][tc + s - 1] = t
chessboard_cover(board, tr, tc, tr + s - 1, tc + s - 1, s)
# 右上子棋盘
if dr < tr + s and dc >= tc + s:
chessboard_cover(board, tr, tc + s, dr, dc, s)
else:
board[tr + s - 1][tc + s] = t
chessboard_cover(board, tr, tc + s, tr + s - 1, tc + s, s)
# 左下子棋盘
if dr >= tr + s and dc < tc + s:
chessboard_cover(board, tr + s, tc, dr, dc, s)
else:
board[tr + s][tc + s - 1] = t
chessboard_cover(board, tr + s, tc, tr + s, tc + s - 1, s)
# 右下子棋盘
if dr >= tr + s and dc >= tc + s:
chessboard_cover(board, tr + s, tc + s, dr, dc, s)
else:
board[tr + s][tc + s] = t
chessboard_cover(board, tr + s, tc + s, tr + s, tc + s, s)
size = 8
board = [[0] * size for _ in range(size)]
special_row = 3
special_col = 4
board[special_row][special_col] = -1
tile_count = 0
chessboard_cover(board, 0, 0, special_row, special_col, size)
for row in board:
print(row)
[2, 2, 3, 3, 7, 7, 8, 8]
[2, 1, 1, 3, 7, 6, 6, 8]
[4, 1, 5, 5, 9, 9, 6, 10]
[4, 4, 5, 0, -1, 9, 10, 10]
[12, 12, 13, 0, 0, 17, 18, 18]
[12, 11, 13, 13, 17, 17, 16, 18]
[14, 11, 11, 15, 19, 16, 16, 20]
[14, 14, 15, 15, 19, 19, 20, 20]