奶牛跑步 n 分鐘,疲勞度上限 m。每分鐘可選跑或休息:
求 n 分鐘後疲勞度為 0 時的最大跑步距離。n ≤ 10000, m ≤ 500。
dp[i][j]:前 i 分鐘,當前疲勞度為 j 的最大距離。j=0 表示未疲勞或剛休息完。
dp[i][j+1] = max(dp[i][j+1], dp[i-1][j] + v[i])。dp[i+j-1][0] = max(dp[i+j-1][0], dp[i-1][j])。dp[i][0] = max(dp[i][0], dp[i-1][0])。#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 10005;
const int MAXM = 505;
int dp[MAXN][MAXM];
int v[MAXN];
int main() {
int n, m;
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 1; i <= n; i++) scanf("%d", &v[i]);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
if (j > 0 && i + j - 1 <= n)
dp[i+j-1][0] = max(dp[i+j-1][0], dp[i-1][j]);
else
dp[i][0] = max(dp[i][0], dp[i-1][0]);
if (j < m)
dp[i][j+1] = max(dp[i][j+1], dp[i-1][j] + v[i]);
}
}
printf("%d\n", dp[n][0]);
}
return 0;
}
i+j-1 <= n 避免越界。dp[0][0]=0,其餘 0(距離非負)。POJ 3661 是狀態機 DP 經典題:疲勞度作為狀態,跑/休息對應不同轉移。休息的強制連續性導致跳躍轉移,需仔細處理邊界。代碼簡潔,是二維 DP 狀態機的優秀範例。