Alpha-Beta 剪枝

有一个简单的博弈问题:

现在有一颗 \(n\) 个点的树,每次询问后给出一个点连接的所有子节点。

Alice 和 Bob 在树上博弈。

Alice 和 Bob 每次可以将点向下移动一格。

如果到了叶子节点,便不再移动,交互库给出叶子权值。

Alice 希望选的数最大,Bob 反之。

求:到达的数最后是多少?

显然有 \(\mathcal O(n)\) 做法:

\[f(i,0) = \max_{v\in son_i} f(v,1) \]

\[f(i,1) = \min_{v\in son_i} f(v,0) \]

但是我们询问次数想要尽可能小。

若我们搜索到了一个点。

我们维护两个变量 \(\alpha,\beta\)

\(\alpha\) 表示现在可以至少取到 \(\alpha\)

\(\beta\) 表示现在走到该子树内可以取到的最大值。

最后 \(\alpha \ge \beta\) 时直接退出即可,因为显然不优。

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;
  }
}

引用了 oi-wiki 上的代码。

posted @ 2024-09-06 19:01  WhisperingWillow  阅读(42)  评论(0编辑  收藏  举报