题意:有最多100天 每天有一个食物量 你一开始有一个最大胃口表示你最开始能吃多少食物
如果你昨天吃了 那么今天的胃口为昨天的2/3 如果你前天吃了 昨天没吃 那么你的胃口可以恢复到前天的情况
如果你有连续两天没吃了 那么你就可以恢复到最大胃口了 问怎样安排使一共吃到的食物最多
题解:就裸裸的DP了,反正从没出过DP(的DP选手
dp[i][j][k]表示第i天结束后 当前的胃口能级为j 这一天进行的操作k k为0表示今天吃了 k为1表示今天没吃
那么转移也没什么难的了 转移模拟这几种状态即可
今天吃由昨天转移来的
dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - 1][0] + 今天吃);
dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j][0]); 今天不吃
今天吃由前天转移来的 dp[i][j][0] = max(dp[i][j][0], dp[i - 2][j][0] + 今天吃]));
还要处理一下由大前天转移过来的 这时候你今天吃 能级就为1 今天不吃能级就为0
反正就xjb搞吧... 我和铜牌题打起来了

#include <bits/stdc++.h> using namespace std; int q[105]; int e[105]; int dp[105][105][5]; int main() { int n, m; scanf("%d%d", &n, &m); memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++) scanf("%d", &q[i]); e[1] = m; for(int i = 2; i <= n; i++) e[i] = e[i - 1] * 2 / 3; for(int i = 1; i <= n; i++) { dp[i][1][0] = min(q[i], e[1]); if(i > 2) { for(int j = 0; j <= i - 3; j++) { dp[i][1][0] = max(dp[i][1][0], dp[i - 3][j][0] + min(q[i], e[1])); dp[i][1][0] = max(dp[i][1][0], dp[i - 3][j][1] + min(q[i], e[1])); } } if(i > 1) { for(int j = 0; j <= i - 2; j++) { dp[i][0][1] = max(dp[i][0][1], dp[i - 2][j][0]); dp[i][0][1] = max(dp[i][0][1], dp[i - 2][j][1]); } } for(int j = 1; j <= i; j++) { dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - 1][0] + min(q[i], e[j])); dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j][0]); if(i > 1) dp[i][j][0] = max(dp[i][j][0], dp[i - 2][j][0] + min(q[i], e[j])); } } int ans = 0; for(int i = 1; i <= n; i++) { for(int j = 0; j <= i; j++) for(int k = 0; k < 2; k++) ans = max(ans, dp[i][j][k]); } printf("%d ", ans); return 0; } /* 8 900 900 600 40 400 20 266 10 177 */