hiro1729 競プロ

競プロの解説などを書きます。

ABC261-D 解説

D - Flipping and Bonus

DPをします。$dp[$(0-indexedで)$i$回目のコイントスで$][j$回連続で表が出ているとき$]$のこれまでもらったお金の最大値 というDPができます。遷移は、$i$連続の連続ボーナスを$Bonus[i]$(なければ$0$)とすると、

$dp[i][0]=max(dp[i-1])$

$1 \le j \le i+1$のとき $dp[i][j]=dp[i-1][j-1]+X[i]+Bonus[j]$

で、答えは$max(dp[N-1])$です。

N, M = map(int, input().split())
X = list(map(int, input().split()))
Bonus = [0] * (N + 1)
for _ in range(M):
    C, Y = map(int, input().split())
    Bonus[C] = Y
dp = [[0] * (N + 1) for _ in range(N)]
dp[0][1] = X[0] + Bonus[1]
for i in range(1, N):
    dp[i][0] = max(dp[i - 1])
    for j in range(1, i + 2):
        dp[i][j] = dp[i - 1][j - 1] + X[i] + Bonus[j]
print(max(dp[N - 1]))
#include <bits/stdc++.h>
using namespace std;

int main() {
    int N, M;
    cin >> N >> M;
    vector<int> X(N);
    for (int i = 0; i < N; i++) {
        cin >> X[i];
    }
    vector<int> Bonus(N + 1);
    for (int i = 0; i < M; i++) {
        int C, Y;
        cin >> C >> Y;
        Bonus[C] = Y;
    }
    vector<vector<long long>> dp(N, vector<long long>(N + 1));
    dp[0][1] = X[0] + Bonus[1];
    long long mx = dp[0][1];
    for (int i = 1; i < N; i++) {
        dp[i][0] = mx;
        for (int j = 1; j <= i + 1; j++) {
            dp[i][j] = dp[i - 1][j - 1] + X[i] + Bonus[j];
            if (mx < dp[i][j]) {
                mx = dp[i][j];
            }
        }
    }
    cout << mx << '\n';
}