这道题是一到比较水的DP,其实看看就能猜到状态转移方程,因为已经是一个定型。
dp[i][j]表示的是当第i分钟门的打开程度为j的时候获得的最大繁荣度,很容易推知方程dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1], dp[i - 1][j + 1]) + w,w表示的是这一分钟能够获得的繁荣度,注意处理边界情况。
最开始我按照常规办法写,结果果断的奉献了一次MLE,所以我就参照了网上的滚动写法,然后就A了。
#include <cstdio>
#include <cstring>
#include <algorithm>
struct data{
int t, p, s;
}a[111];
int dp[2][111];
bool f[30010];
int main(){
int n, t, k;
while(~scanf("%d%d%d", &n, &k, &t)){
memset(dp, 0, sizeof(dp));
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; i++){
scanf("%d", &a[i].t);
f[a[i].t] = 1;
}
for (int i = 1; i <= n; i++)
scanf("%d", &a[i].p);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i].s);
for (int i = 0; i <= t; i++)
for (int j = 0; j <= i && j <= k; j++){
int w = 0;
if (f[i])
for (int p = 1; p <= n; p++)
if (a[p].t == i && a[p].s == j)
w += a[p].p;
if (j == 0) dp[i % 2][j] = std::max(dp[1 - i % 2][j], dp[1 - i % 2][j + 1]);
else if (j == k) dp[i % 2][j] = std::max(dp[1 - i % 2][j], dp[1 - i % 2][j - 1]);
else dp[i % 2][j] = std::max(dp[1 - i % 2][j], std::max(dp[1 - i % 2][j - 1], dp[1 - i % 2][j + 1]));
dp[i % 2][j] += w;
}
int ans = 0;
for (int j = 0; j <= k; j++)
ans = std::max(dp[t % 2][j], ans);
printf("%d\n", ans);
}
return 0;
}