文章目录
一、图的应用-骑士周游问题
骑士周游问题
- 在一个8×8的国际象棋棋盘上,一个棋子“马”(骑士),按照“马走日”的规则,从一个格子出发,要走遍所有棋盘格恰好一次。把一个这样的走棋序列称为一次“周游”
- 采用图搜索算法,解决骑士周游问题
- 将合法走棋次序表示为一个图
- 采用图搜索算法搜寻一个长度为(行×列-1)的路径,路径上包含每个顶点恰一次
构建骑士周游图
- 将棋盘格作为顶点,按照“马走日”规则的走棋步骤作为连接边。建立每一个棋盘格的所有合法走棋步骤能够到达的棋盘格关系图
- 一个8×8的国际象棋棋盘,行编号从07,列编写从07。整个棋盘从左下角到右上角的编号为0~63。
构建骑士周游图Python实现
def is_legal(x, y, size=8):
"""判断坐标(x,y)是否在棋盘上"""
if x < 0 or x >= size:
return False
if y < 0 or y >= size:
return False
return True
def get_next_positions(x, y, size=8):
"""从当前坐标(x,y)出发,马走日能到达的棋盘位置"""
options = [(2, -1), (2, 1), (1, 2), (-1, 2), (-2, 1), (-2, -1), (-1, -2), (1, -2)]
next_positions = []
for option in options:
next_pos = (x + option[0], y + option[1])
if is_legal(*next_pos):
next_positions.append(next_pos)
return next_positions
def get_node_id(row, col, size=8):
"""计算顶点ID"""
return row * size + col
def knight_graph(size=8):
"""构建骑士周游图"""
g = Graph()
# 遍历每个格子
for row in range(size):
for col in range(size):
begin_node_id = get_node_id(row, col)
for pos in get_next_positions(row, col):
end_node_id = get_node_id(pos[0], pos[1])
g.add_edge(begin_node_id, end_node_id)
return g
k_graph = knight_graph()
for i in k_graph.vertexes.values():
print(i)
print(f"一共{
k_graph.get_edge_count()}条边")
### 输出结果
0 connected to : [17, 10]
17 connected to : [32, 34, 27, 11, 2, 0]
10 connected to : [25, 27, 20, 4, 0, 16]
1 connected to : [16, 18, 11]
16 connected to : [33, 26, 10, 1]
18 connected to :