极大极小算法是一种空间搜索零和博弈算法!使得对手利益最小化我方利益最大化!
在局面确定的双人对弈里,常进行对抗搜索,构建一棵每个节点都为一个确定状态的搜索树。奇数层为己方先手,偶数层为对方先手。搜索树上每个叶子节点都会被赋予一个估值,估值越大代表我方赢面越大。我方追求更大的赢面,而对方会设法降低我方的赢面,体现在搜索树上就是,奇数层节点(我方节点)总是会选择赢面最大的子节点状态,而偶数层(对方节点)总是会选择我方赢面
Minimax 算法的整个过程,会从上到下遍历搜索树,回溯时利用子树信息更新答案,最后得到根节点的值,意义就是我方在双方都采取最优策略下能获得的最大分数。
例题
约定inf为无穷,以这棵树为例,题目服用了南京财经大学蒋玖川老师的课堂习题为例,请老师见谅。
第一步我们进行初始化a=-inf beta=+inf 在这里我们从左到右开始遍历树,首先初始化从根节点,传递根节点的值到左边的可选择的节点
开始搜索!
可知最左边的叶子节点为5,由于max节点现在具有可决策选择,故更新该节点的val为5,且a更新为5,beta不更新,由于分数为5的节点的a
在完成最左边max层的值确认后,更新D的取值范围,由于D是min,故D的beta更新为5,a不更新
D将开始搜索他的右子树,此时传递D的a与beta的值给E
E开始搜索他的左子树,发现E的左子节点的值为10,E更新a为10,由于E节点的a>beta,故进行beta剪支减去剩余的子节点,
此时根节点的左子树搜索完成,更新根节点的a与beta的值,由于根节点是最大选择,故根节点的a更新为5,beta不更新。
开始遍历根结点中间的子树,同样传递根节点的a与beta给中间的子树
开始搜索中间的子树,从中间子树的最左边字数开始搜索,发现1、2、2当中最大的为2,更新他的父节点的a值为2,此时F节点的值需要进行更新,由于F是最小选择层,故设置beta为2,由于a>beta,故进行剪掉F节点的右子树
更新F的分数为2,由于F值为2,根节点一句贪心算法局部最优点不会选择她,所以不需要更新根结点的a值。下面开始搜索根节点的右子树的,同样刚开始也是传递根节点的a和beta值给右子树的具有选择权力的左边的节点
搜索G节点的子结点,发现G的子节点为12,更新G的a=12以及G的分数等于12,同时更新G节点的父节点B的beta的值为12,此时G节点的a 继续搜索B的中间的子树,同样传递B的a与beta值给到B的中间的子节点M M开始搜索,由于M是最大选择,M的最大子节点为4,更新M的a与分数为4,此时M的a不大于M的beta的值,所以不进行剪支 同时更新B节点的选择范围,B由于是最小选择,他的beta目前可更新为M点的分数为4,此时B点的a为5,beta为4,a>beta,所以对B为未搜索的子树进行剪纸,不再搜索 最后所有子树搜索完毕,更根节点进行最大化利益选择为5 算法实现: int alpha_beta(int u, int alph, int beta, bool is_max) { if (!son_num[u]) return val[u]; if (is_max) { for (int i = 0; i < son_num[u]; ++i) { int d = son[u][i]; alph = max(alph, alpha_beta(d, alph, beta, is_max ^ 1)); if (alph >= beta) break; } return alph; } else { for (int i = 0; i < son_num[u]; ++i) { int d = son[u][i]; beta = min(beta, alpha_beta(d, alph, beta, is_max ^ 1)); if (alph >= beta) break; } return beta; } }