Alpha-Beta 剪枝

WhisperingWillow發表於2024-09-06

有一個簡單的博弈問題:

現在有一顆 \(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 上的程式碼。

相關文章