EDPC L - Deque

両端取り

考え方

ABCでいうと、E問題級。

値というよりは範囲を広げていく動的計画法、通称区間 DP。
といっても、そこまで特殊な考えなわけではない。
左端と右端の位置を使った $2$ 次元の動的計画法で、初期値を入れる場所と継承の方向が少し独特なだけ。

まず、問題を少しわかりやすく言い換える。
太郎君は $X-Y$ を最大化しようとし、次郎君は最小化する、とあるが、これはわかりにくい。
太郎君は $X-Y$ を最大化しようとし、次郎君は $Y-X$ を最大化しようとする、の方がよい。

なぜなら、その変更によって、単純な対戦ゲームになるから。
各局面で、自分の全行動について「その行動で得る点 $-$ その後の最善手での結果」を求めればよい。
採用するのは、そのうちの最大値である。

終了パターンがある程度限られることもあり、バックトレースで考えることになる。

あとは、これをコードにすればよい。

計算量は $O(N^2)$。

入力例1での動作

入力を受け取る。

n: 4
a: {10, 80, 90, 30}

dp[l][r] を、区間 a[l] から a[r] までが残っているときの、
現在の手番の人の得点 $-$ 相手の得点の最大値とする。

最初に、次のように初期化する。
残り $1$ つの場合、それを取るしか選択肢がないので、その得点がそのまま最大値になる。

左端\右端 10 80 90 30
10 10 - - -
80 - 80 - -
90 - - 90 -
30 - - - 30

次に、たとえば dp[2][3] を考える。
このマスは、{90, 30} という状態での先手の得点予測である。

左端から取る場合、まず自分に $90$ 点入る。
その後の展開は、下のマスを見れば、相手の方が $30$ 点多くなる展開が予測できる。
つまり、左端から取った場合の得点予測は $60$ 点となる。

同様に、右端から取る場合、自分に $30$ 点、その後相手が $90$ 点多く取るので、得点予測は $-60$ 点となる。
よって、多い方を考えて、ここの得点予測は $60$ 点となる。

dp[2][3] = max(90 - dp[3][3], 30 - dp[2][2])
         = max(60, -60)
         = 60

この提出コードでは、表の下段から順に、左から埋めていく。
具体的には、次の順に値が確定する。

dp[2][3]
dp[1][2] -> dp[1][3]
dp[0][1] -> dp[0][2] -> dp[0][3]

実際に埋めると、次のようになる。

左端\右端 10 80 90 30
10 10 70 20 10
80 - 80 10 20
90 - - 90 60
30 - - - 30

右上の $10$ が答えである。
左下部分はメモリが無駄になるので、実務だったらちょっと考えないといけないが、競プロなら関係ない。

注意点

答えは、int 型からはみ出る。
DP テーブルを含め、long long 型を用いること。

別解

特になし。