Typical DP Contest B - ゲーム
解法
漸化式的にも解けるが,メモ化再帰で書くほうがわかりやすいかもしれない.
この場合,minimax法でやる.
dp[l][r] := 左の一番上が l 枚目,右の一番上が r 番目の状態から始めた時の,(その瞬間の)先手の得点 - 後手の得点の最大値
としてメモ化再帰する.
答えは sum を全カードの総和として (sum + dp[0][0]) / 2 で求まる.
ソースコード
#include <bits/stdc++.h> using namespace std; constexpr int inf = 1e9; int main() { int A, B; cin >> A >> B; vector<int> a(A), b(B); for(auto& x : a) cin >> x; for(auto& x : b) cin >> x; const int sum = accumulate(a.begin(), a.end(), 0) + accumulate(b.begin(), b.end(), 0); vector<vector<int>> dp(A + 1, vector<int>(B + 1, -inf)); function<int(int, int)> rec = [&] (int l, int r) { if(dp[l][r] != -inf) return dp[l][r]; if(l == A && r == B) return dp[l][r] = 0; int& res = dp[l][r]; if(l != A) res = a[l] - rec(l + 1, r); if(r != B) res = max(res, b[r] - rec(l, r + 1)); return res; }; cout << (sum + rec(0, 0)) / 2 << endl; }