[ABC270D] Stones

yabnto發表於2023-05-17

[ABC270D] Stones

題意

有兩個人玩遊戲,有 \(n\) 個石子,和一個長度為 \(k\) 的序列,每次可以取 \(a_i\) 個但前提是剩下來的石子數有 \(a_i\) 個,第一個人先取,問兩邊都是用最優策略時,第一個人最多能得多少個石子。

思路

可以設計狀態 \((x, y, f)\) 表示第一個人取了 \(x\) 個石子,第二個人取了 \(y\) 個石子,由第 \(f + 1\) 人開取,顯然 \(x + y \le n\)

那麼可以最佳化狀態,因為要求的是第一個人最多能得多少個石子,所以可以將其中一個變數提取出來變成最優屬性,可是光靠知道另一個人取了多少個石子是不夠的,所以可以將它變成一共已經取了 \(x\) 個石子,還有由於兩個人都用的是最優策略,所以 \(f\) 可以最佳化掉,也就變成了 \(dp_x = y\),那轉移就是 \(dp_x = \max(x - dp_{x - a_i})\)

程式碼

#include <iostream>

using namespace std;

const int MaxN = 110, MaxV = 1e4 + 10;

int dp[MaxV], a[MaxN], n, k;

int main() {
  cin >> n >> k;
  for (int i = 1; i <= k; i++) {
    cin >> a[i];
  }
  for (int i = 0; i <= n; i++) {
    for (int j = 1; j <= k; j++) {
      if (i >= a[j]) {
        dp[i] = max(dp[i], i - dp[i - a[j]]);
      }
    }
  }
  cout << dp[n] << endl;
  return 0;
}