CF505C题解
题意
给定
首先给人的感觉是一道贪心题,但是并没有什么好的贪心思路。对于这种每一步决策都对后续决策有影响的题目考虑DP,首先设
其中
注意到数据范围,如果是
我们考虑有哪些状态才能被转移,假设第一次移动的步数为
Code
在代码中贴了详细注释。
constexpr int N = 30005, D = 400;
int n, d, cnt[N], f[N][(D << 1) + 10];
int main() {
// read 是快读,这里不给出实现
read(n), read(d);
for (int i = 1; i <= n; ++i) {
int pos;
read(pos);
++cnt[pos];//统计每个位置的宝藏数量
}
memset(f, -0x3f, sizeof(f));
f[d][D] = cnt[0] + cnt[d];//考虑第一步走 d 步,于是初始状态直接设置在 d 位置
// 我们将 D 看作零点,防止出现负下标
int ans = 0;
for (int i = d + 1; i <= 30000; ++i) {
for (int j = -D; j <= D; ++j) {
for (int k = -1; k <= 1; ++k) {
int step = j + d + k; // 这一步的步长
if (step < 1 || i + step > 30000 || j + k < -D || j + k > D)
continue;
f[i + step][j + k + D] = max(f[i + step][j + k + D], f[i][j + D] + cnt[i + step]);//这个dp式子与朴素的dp式子是相同的
}
ans = max(ans, f[i][j + D]);
}
}
write(ans);
return 0;
}