D - Flipping and Bonus Editorial by en_translator
The key fact is that, for \(0\leq i\leq N-1\), “if we know the value of the counter \(C\) when the \(I\)-th toss finished, the maximum amount of money we can earn in the \((i+1)\)-th through \(N\)-th toss is independent of the outcome of the \(1\)-st through \(i\)-th toss (as long as the value of the counter results in \(C\)).
Thus, it is sufficient to incrementally update the maximum amount of money obtained by the \(1\)-st through \(i\)-th toss subject to “after the first \(i\) tosses,” “the value of the counter becomes \(j\).” Let us denote this maximum value by \(dp[i][j]\) (where DP stands for Dynamic Programming). If such situation is impossible, that is, if \(i<j\), then let \(dp[i][j]=-\infty\).
First, we consider the initial value \(dp[0][j]\). Since the initial value of the counter is \(0\), we have \(dp[0][0]=0, dp[0][j]=-\infty\) \((j>0)\).
Next, we consider how to update the DP array.
Let us consider how to compute \(dp[i_0+1][j]\) when we have obtained \(dp[i][j]\) for \(0\leq i\leq i_0\).
First, consider \(j_0>0\). Such case happens only if the counter shows \(j_0-1\) after the \(i_0\)-th toss and the coin heads in the \((i_0+1)\)-th toss. Thus,
\(dp[i_0+1][j_0]=dp[i_0][j_0-1]+X_{i_0+1}+B_{j_0}\). Here, \(B_{j_0}\) is a streak bonus: \(B_{j_0}=Y_k\) if there exists \(k\) such that \(C_k=j_0\), or \(B_{j_0}=0\) otherwise.
Then, \(j_0=0\) holds only when the coin tails in the \((i_0+1)\)-th toss. Thus, \(dp[i_0+1][0]=\displaystyle\max_j(dp[i_0][j])\). Noting that \(dp[i_0][j]=-\infty\) if \(i_0<j\), we have \(dp[i_0+1][0]=\displaystyle\max_{0\leq j\leq i_0}(dp[i_0][j])\).
The answer is \(\displaystyle\max_{0\leq j\leq N}(dp[N][j])\).
The overall complexity is \(O(N^2)\), which is fast enough. Therefore, the problem has been solved.
Sample code in C++:
#include <bits/stdc++.h>
using namespace std;
int main(void) {
int n, m;
long long x[5001];
long long c, y;
long long b[5001], dp[5001][5001];
long long ans;
for (int i = 0; i <= n; i++)b[i] = 0;
cin >> n >> m;
for (int i = 0; i < n; i++)cin >> x[i + 1];
for (int i = 0; i < m; i++) {
cin >> c >> y;
b[c] = y;
}
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) dp[i][j] = dp[i - 1][j - 1] + x[i] + b[j];
dp[i][0] = 0;
for (int j = 0; j < i; j++)dp[i][0] = max(dp[i][0], dp[i - 1][j]);
}
ans = 0;
for (int i = 0; i <= n; i++)ans = max(ans, dp[n][i]);
cout << ans << endl;
return 0;
}
posted:
last update: