骑士巡游问题:常规解法与启发式方法优化
来源:互联网 发布:php 位数补全 编辑:程序博客网 时间:2024/04/28 17:53
The knight’s tour puzzle is played on a chess board with a single chess piece, the knight. The object of the puzzle is to find a sequence of moves that allow the knight to visit every square on the board exactly once. One such sequence is called a “tour.” The knight’s tour puzzle has fascinated chess players, mathematicians and computer scientists alike for many years. The upper bound on the number of possible legal tours for an eight-by-eight chessboard is known to be 1.305×10351.305×1035; however, there are even more possible dead ends. Clearly this is a problem that requires some real brains, some real computing power, or both.
Although researchers have studied many different algorithms to solve the knight’s tour problem, a graph search is one of the easiest to understand and program. Once again we will solve the problem using two main steps:
Represent the legal moves of a knight on a chessboard as a graph.
Use a graph algorithm to find a path of length rows×columns−1rows×columns−1 where every vertex on the graph is visited exactly once.
解题代码:
"""knight tour problem"""from pythonds.graphs import Graphclass KnightProblem(object): """ solution class bd_size: 方阵棋盘的边长(以格数计数) step: knight的步伐(移动方式) """ def __init__(self, bd_size): self.bd_size_ = bd_size self.knight_graph_ = Graph() self.step_ = [(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1)] def build_knight_graph(self): """ 构建 knight graph """ for row in range(self.bd_size_): for col in range(self.bd_size_): current_id = self.gener_node_id(row, col) for nid in self.get_next_nodes(row, col): self.knight_graph_.addEdge(current_id, nid) def gener_node_id(self, row, col): """ 根据当前所在行、列生成该结点的序号 算法:序号 = row * bd_size + col """ return row * self.bd_size_ + col def get_next_nodes(self, row, col): """ 获取从当前所在结点的下一个合法移动所到达的结点 """ next_nodes = [] for move in self.step_: new_row = row + move[0] new_col = col + move[1] if self.is_legal_node(new_row, new_col): nid = self.gener_node_id(new_row, new_col) next_nodes.append(nid) return next_nodes def is_legal_node(self, row, col): """ 判断此结点是不是一个合法结点 算法:row/col > 0 and < bd_size """ if row < 0 or row > self.bd_size_: return False elif col < 0 or col > self.bd_size_: return False else: return True def dfs(self, current_vertex, vertex_path, current_depth=0): """ 深度优先搜索 recursion """ current_vertex.setColor('gray') vertex_path.append(current_vertex) # base case if current_depth < self.bd_size_ * self.bd_size_ - 1: done = False # 获取当前结点的所有相邻结点 i = 0 # 常规解法,不采取启发式优化,找出遍历8*8规格的棋盘, #一般笔记本可能需要半小时 # nbrs = list(current_vertex.getConnections()) # 采用启发式优化,则在1s内完成 nbrs = self.order_by_avail(current_vertex) while not done and i < len(nbrs): if nbrs[i].getColor() == 'white': done = self.dfs(nbrs[i], vertex_path, current_depth + 1) i += 1 if not done: # perparing to trace back vertex_path.pop() current_vertex.setColor('white') else: done = True return done def order_by_avail(self, current_vertex): """ 启发式优化 根据各邻近结点的未访问子节点数 n_avail 对当前结点的邻近结点进行ascending排序 """ res_list = [] # nbr为当前结点的邻近结点 for nbr in current_vertex.getConnections(): if nbr.getColor() == 'white': c = 0 for n in nbr.getConnections(): if n.getColor() == 'white': c += 1 res_list.append((nbr, c)) res_list.sort(key=lambda x:x[1]) return [y[0] for y in res_list]if __name__ == '__main__': kf_graph = KnightProblem(8) kf_graph.build_knight_graph() path = [] print(kf_graph.dfs(kf_graph.knight_graph_.getVertex(0), path)) print(path)
启发式优化的思想是:让knight一开始尽量绕着棋盘的边缘游走。
因为棋盘边缘的可走路径少(2或3),而棋盘中间可走路径多(8),因此能先遍历边缘结点,使迭代次数减少。到了knight游走后期,虽然knight不得不走到棋盘中间,但因为边缘的结点已被遍历过(游戏规则是一个结点只能遍历一次),此时即使在棋盘中间,可走的路径也大大减少了。通过人类的智慧,启发式方法的达到了极其优化的效果。
- 骑士巡游问题:常规解法与启发式方法优化
- 骑士巡游问题的解法
- 骑士巡游问题算法
- 骑士巡游问题
- 骑士巡游问题
- 骑士巡游问题 python
- 骑士巡游问题
- 骑士巡游
- 骑士巡游问题源码C语言描述
- 用java解决骑士巡游问题
- 骑士巡游问题的warnsdorff规则
- 【搜索】骑士巡游问题,简称746弯
- 骑士巡游问题的C++代码
- 程序设计大赛---骑士巡游
- 每天刷个算法题20160523:骑士巡游的递归转非递归解法
- 骑士巡游 马踏棋盘
- 数据结构学习之启发式搜索求解骑士周游问题
- 八皇后问题(dfs常规解法)
- QT使用注意总结
- 时间戳
- 反思——误删服务器中的备份
- java mail使用中遇到的550类型错误
- 关于Python中的import(二)
- 骑士巡游问题:常规解法与启发式方法优化
- applicationcontext.xml
- Python网络数据采集
- opencv3.1
- js对象+匿名函数的使用
- 用系统日志了解你的 Linux 系统
- 【逆向学习】暗号 writeup
- 【每日安全资讯】德国反垄断机构:Facebook滥用支配地位收集用户数据
- 25000 位阿里工程师,刚刚放出一个大招!