题意:背景吃饭,初始可以吃m,若之后连续吃每次是上一次的2/3(是可以吃的2/3,不是实际吃的2/3),若中间隔一次没吃,下一次可以和上一次吃的一样多,若连续两次不吃,下一次又可以吃m。每次有一个可以吃的上限。求最多可以吃多少。
思路:dp[i][j] 表示到第 i 次吃了 j 次能吃到的最大值。
//a[]是上限值,b[]是实际能吃值,注意各取值范围
dp[i][j] = max(dp[i][j], dp[i-1][j-1] + min(a[i], b[j]));
dp[i][j] = max(dp[i][j], dp[i-2][j] + min(a[i], b[j]));
dp[i][j] = max(dp[i][j], max(dp[i-3][k]) + min(a[i], m));
从前向后推也类似
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 105;
int n, m, a[maxn], dp[maxn][maxn], b[maxn];
int main(){
cin >> n >> m;
b[0] = m;
for(int i=1; i<=n; i++) {
cin >> a[i];
b[i] = b[i-1]*2/3;
dp[i][0] = min(a[i], m);
}
for(int i=1; i<=n; i++){
for(int j=0; j<=i; j++){
if(i+1<=n)
dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j] + min(a[i+1], b[j+1]));
if(i+2<=n && n >= 2)
dp[i+2][j] = max(dp[i+2][j], dp[i][j] + min(a[i+2], b[j]));
dp[i+3][0] = max(dp[i+3][0], dp[i][j] + min(a[i+3], m));
}
}
int ans = 0;
for(int i=0; i<=n; i++) ans = max(ans, dp[n][i]);
cout << ans << endl;
}