初学者的个人笔记,不足之处还请指正,谢谢
极小化极大算法(minimax) L'algorithm minimax
极小化极大算法是一个深度优先的搜索算法,树形结构递归,一般在棋类等两方较量的游戏和程序中运用较多,如tic-tac-toe
它需要满足零总和博弈,比如在一场棋类比赛中,我方得分,对方失分,总分值永远为0或者某一常数
因此,我们为了获胜,即需要最大化我方利益(Max),最小化对方利益(Min)
伪代码如下(来自Wikipedia):
function minimax(node, depth) if node is a terminal node or depth = 0 return the heuristic value of node if the adversary is to play at node let α := +∞ foreach child of node α := min(α, minimax(child, depth-1)) else {we are to play at node} let α := -∞ foreach child of node α := max(α, minimax(child, depth-1)) return α
第一个if伪代码块指出了函数递归的两个出口,一是depth=0即到达了层数顶点,游戏结束,二是递归到了某一节点,程序无法再进行,或者已经有一方获胜。
第二个if伪代码块指出,当处于对方节点时,取最小值
否则else 位于我方节点时,取最大值
由于minimax算法是一个树形结构,所以总共需要计算n的x次方个结果,对于棋盘比较大的游戏来说,计算量成几何倍数增长,于是我们需要用到Alpha-beta剪枝,来优化这个算法
Alpha-beta剪枝 L'algorithme Alpha-beta
根据上文提到的,alpha-beta剪枝实际上就是minimax的升级版本
将minimax的搜索树,剪裁掉无意义无需搜索的枝干以提升搜索效率,减少工作量
伪代码如下(来自Wikipedia):
01 function alphabeta(node, depth, α, β, maximizingPlayer) // node = 节点,depth = 深度,maximizingPlayer = 大分玩家 02 if depth = 0 or node是终端节点 03 return 节点的启发值 04 if maximizingPlayer 05 v := -∞ 06 for 每个子节点 07 v := max(v, alphabeta(child, depth - 1, α, β, FALSE)) // child = 子节点 08 α := max(α, v) 09 if β ≤ α 10 break // β裁剪 11 return v 12 else 13 v := ∞ 14 for each 每个子节点 15 v := min(v, alphabeta(child, depth - 1, α, β, TRUE)) 16 β := min(β, v) 17 if β ≤ α 18 break // α裁剪 19 return v