knight_tour 骑士游历算法

knight_tour 骑士游历算法

  • 1、问题描述
    在一个N*M的棋盘上,在任意位置放置一个骑士,骑士的走"日字",和象棋中的马一样。

    问该骑士能否不重复遍历整个棋盘。下面的方法本质还是穷举,所以就写成可以计算出共有多少种不同的遍历方法。

  • 2、分析与思路
    根据题意,骑士走的下一步可能在棋盘上有多种选择(最多8种),需要选择1种,然后继续走下去,直到无处可走。

    无处可走时有两种情况:

    • 情况一:成功完成了遍历,那么接下来就通过回溯(回到上一步的位置,重新选择下一步的位置),寻找其他的走法。
    • 情况二:未完成遍历,接下来还是要通过回溯继续寻找能够完成遍历的走法。

算法

  • get_valid_pos 找出骑士可以从当前位置移动到的所有有效位置
def get_valid_pos(
    position: Tuple[int, int],   # 当前位置
     n: int)                     # 棋盘大小
-> List[Tuple[int, int]]:
  • is_complete 检查板(矩阵)是否已完全填满非零值
def is_complete(
    board: List[List[int]]  #棋盘
) 
-> bool:
  • open_knight_tour_helper 助手功能,解决骑士游览问题。
def open_knight_tour_helper(
    board: List[List[int]],   # 棋盘
    pos: Tuple[int, int],     # 位置
    curr: int                 # 当前步数 
) -> bool:
  • open_knight_tour 求大小为n的板的骑士旅行问题的解
def open_knight_tour(n: int) -> List[List[int]]:
    """
    Find the solution for the knight tour problem for a board of size n. Raises
    ValueError if the tour cannot be performed for the given size.

代码

[knight_tour.py]{..\src\backtracking\knight_tour.py}

"""
Prepare
   1. sys.path 中增加 TheAlgorithms\src 子模块

"""
import sys
sys.path.append('E:\dev\AI\TheAlgorithms\src')

案例一:

找出骑士可以从当前位置移动到的所有有效位置

def get_valid_pos(
    position: Tuple[int, int],   # 当前位置
     n: int)                     # 棋盘大小
-> List[Tuple[int, int]]:
    y, x = position
    positions = [
        (y + 1, x + 2),
        (y - 1, x + 2),
        (y + 1, x - 2),
        (y - 1, x - 2),
        (y + 2, x + 1),
        (y + 2, x - 1),
        (y - 2, x + 1),
        (y - 2, x - 1),
    ]
from backtracking.knight_tour import get_valid_pos
"""
"""
print(get_valid_pos((1, 3), 4))  #    [(2, 1), (0, 1), (3, 2)]

print(get_valid_pos((1, 3), 10))  



[(2, 1), (0, 1), (3, 2)]
[(2, 5), (0, 5), (2, 1), (0, 1), (3, 4), (3, 2)]

案例二:

检查板(矩阵)是否已完全填满非零值

def is_complete(board: List[List[int]]) 
-> bool:

return not any(elem == 0 for row in board for elem in row)


from backtracking.knight_tour import is_complete
"""
"""

print(is_complete([[1]]))  #    True

print(is_complete([[1, 2], [3, 0]])) #    False

True
False

案例三: 求大小为n的板的骑士旅行问题的解

from backtracking.knight_tour import open_knight_tour
"""
"""
i = 5
thisList = open_knight_tour(i)
# print(list(result))  显示结果不够清晰
print(f'open_knight_tour({i}):')
for i,val in enumerate(thisList):
   print("行号:%s   步骤顺序:%s" % (i + 1, val))

i = 6
thisList = open_knight_tour(i)
# print(list(result))  显示结果不够清晰
print(f'open_knight_tour({i}):')
for i,val in enumerate(thisList):
   print("行号:%s   步骤顺序:%s" % (i + 1, val))
   
open_knight_tour(5):
行号:1   步骤顺序:[1, 14, 19, 8, 25]
行号:2   步骤顺序:[6, 9, 2, 13, 18]
行号:3   步骤顺序:[15, 20, 7, 24, 3]
行号:4   步骤顺序:[10, 5, 22, 17, 12]
行号:5   步骤顺序:[21, 16, 11, 4, 23]
open_knight_tour(6):
行号:1   步骤顺序:[1, 22, 13, 30, 33, 36]
行号:2   步骤顺序:[12, 29, 2, 35, 14, 31]
行号:3   步骤顺序:[21, 8, 23, 32, 3, 34]
行号:4   步骤顺序:[28, 11, 4, 17, 24, 15]
行号:5   步骤顺序:[7, 20, 9, 26, 5, 18]
行号:6   步骤顺序:[10, 27, 6, 19, 16, 25]
posted @ 2021-06-16 14:05  IT88老兵  阅读(314)  评论(0编辑  收藏  举报