abc261D 抛硬币的最大得分

抛n次硬币,对于第i次结果,如果正面朝上,得分为X[i],否则不得分。另外,还设置了m种连正奖励,即如果出现连续C[i]次正面朝上,可额外获得Y[i]得分。求可以获取的最大总得分。
1<=n,m<=5000; 1<=X[i],Y[i]<=1E9; 1<=C[i]<=n

记dp[i][j]表示前i次抛币,当前连正j次的最大得分。如果j!=0,那dp[i][j]只能从dp[i-1][j-1]抛正面得到;如果j==0,可以从所有dp[i-1][x]抛背面得到,其中0<=x<=i-1。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a; i<=b; i++)
#define per(i,a,b) for(int i=b; i>=a; i--)

const int N = 5005;
const int inf = 1E18;
int n, m, X[N], Y[N], dp[N][N];
void solve() {
    cin >> n >> m;
    rep(i,1,n) cin >> X[i];
    rep(i,1,m) {
        int c, y;
        cin >> c >> y;
        Y[c] = y;
    }
    rep(i,1,n) dp[0][i] = -inf;
    rep(i,1,n) {
        rep(j,1,i) dp[i][j] = dp[i-1][j-1] + X[i] + Y[j];
        rep(j,0,i) dp[i][0] = max(dp[i][0], dp[i-1][j]);
    }
    int ans = 0;
    rep(i,0,n) ans = max(ans, dp[n][i]);
    cout << ans << "\n";
}

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}
posted @ 2024-03-11 21:47  chenfy27  阅读(4)  评论(0编辑  收藏  举报