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;
}