title: 9.棋盘覆盖问题
date: 2023-05-05 15:28:11
categories:
- 大学课程内容
- 大二下
- 算法分析基础
9.棋盘覆盖问题
【问题描述】
给定一个2k×2k的棋盘(具体图例见教材),有一个特殊棋格,拥有一个特殊棋格的棋盘称为特殊棋盘。现要用四种L型骨牌(具体图例见教材)覆盖特殊棋盘上除特殊棋格外的全部棋格,不能重叠,找出覆盖方案。
【输入形式】
在屏幕上输入棋盘大小及特殊方格所在行号和列号
【输出形式】
输出使用L型骨牌进行棋盘覆盖结果
【样例输入】
2
1 2
【样例输出】
2 -1 3 3
2 2 1 3
4 1 1 5
4 4 5 5
【样例说明】
输入:第一行输入整数k表示棋盘大小为2的k次幂,若k为2,则棋盘大小为4行4列;第二行输入特殊方格所在的行号和列号,以空格分隔
输出:使用L型骨牌进行棋盘覆盖结果,由3个相同的数表示同一个L型骨牌,不同的骨牌用不同的数字表示。数字的大小表示棋盘覆盖的顺序。特殊方格在棋盘的第1行第2列,用-1表示。各整数间以空格分隔。
思路
使用数学归纳法可知这个问题一定有解,因此可以将整个棋盘分为四个部分,因为有障碍物的那个部分一定是有解的,我们可以把剩下的三个棋盘每个棋盘在切开的位置都看成有障碍物,因此剩下的三个棋盘就都有解了,在3个看成障碍物的地方可以使用一个L型进行覆盖
代码
k = int(input())
obstacle = tuple(map(int, input().split()))
board = [[0 for _ in range(2 ** k)] for _ in range(2 ** k)]
board[obstacle[0]-1][obstacle[1]-1] = -1
# 每个放置的L都需要自己的编号
cnt = 1
def chessboard(board, tr, tc, dr, dc, size):
global cnt
if size == 1:
return
s = size // 2
t = cnt
cnt += 1
# 覆盖左上角子棋盘
if dr < tr + s and 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 and 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 and 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 and 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)
chessboard(board, 0, 0, obstacle[0]-1, obstacle[1]-1, 2 ** k)
for i in range(2 ** k):
for j in range(2 ** k):
print(board[i][j], end=' ')
print()