- dp(i, j): 第i棵树,j高度可以吃到的果子数量——第j高度的果子也被吃了
- dp(i, j) = max(dp(i, j-1)+a(i, j), dp(k, j-delta)+a(i, j)) ( except i)
- 因为j-delta是固定的,所以可以预处理出第j高度的dp最大值来减小复杂度——在代码中是g数组,g[i]代表第i高度的dp最大值
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int data[2010][2010];// data[i][j], 第i棵树第j高度有data[i][j]个果子
long long dp[2010][2010];
long long g[2010];
long long MAX(long long x, long long y) { return x > y ? x : y; }
int main() {
memset(data, 0, sizeof(data));
int N, H, Delta;
scanf("%d%d%d", &N, &H, &Delta);
int tmp1, tmp2;
for (int i = 0; i < N; i++) {
scanf("%d", &tmp1);
for (int j = 0; j < tmp1; j++) {
scanf("%d", &tmp2);
data[i][tmp2]++;
}
}
memset(dp, 0, sizeof(dp));
memset(g, 0, sizeof(g));
for (int i = 1; i <= H; i++) {
for (int j = 0; j < N; j++) {
if (i > Delta) {
dp[i][j] = MAX(dp[i - 1][j] + data[j][i], g[i - Delta] + data[j][i]);
g[i] = MAX(g[i], dp[i][j]);
} else {
dp[i][j] = dp[i - 1][j] + data[j][i];
g[i] = MAX(g[i], dp[i][j]);
}
}
}
long long ans = 0;
for (int i = 0; i < N; i++) {
ans = ans <= dp[H][i] ? dp[H][i] : ans;
}
printf("%lld\n", ans);
}
可以使用一维数组
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int data[2010][2010];// data[i][j], 第i棵树第j高度有data[i][j]个果子
long long dp[2010];
long long g[2010];
long long MAX(long long x, long long y) { return x > y ? x : y; }
int main() {
memset(data, 0, sizeof(data));
int N, H, Delta;
scanf("%d%d%d", &N, &H, &Delta);
int tmp1, tmp2;
for (int i = 0; i < N; i++) {
scanf("%d", &tmp1);
for (int j = 0; j < tmp1; j++) {
scanf("%d", &tmp2);
data[i][tmp2]++;
}
}
memset(dp, 0, sizeof(dp));
memset(g, 0, sizeof(g));
for (int i = 1; i <= H; i++) {
for (int j = 0; j < N; j++) {
if (i > Delta) {
dp[j] = MAX(dp[j] + data[j][i], g[i - Delta] + data[j][i]);
g[i] = MAX(g[i], dp[j]);
} else {
dp[j] = dp[j] + data[j][i];
g[i] = MAX(g[i], dp[j]);
}
}
}
long long ans = 0;
for (int i = 0; i < N; i++) {
ans = ans <= dp[i] ? dp[i] : ans;
}
printf("%lld\n", ans);
}