题意:
长
为
30000
的
一
条
路
长为30000的一条路
长为30000的一条路
有
n
个
位
置
具
有
宝
藏
有n个位置具有宝藏
有n个位置具有宝藏
一
开
始
在
0
位
置
,
第
一
步
走
d
一开始在0位置,第一步走d
一开始在0位置,第一步走d
如
果
上
一
步
走
了
k
,
这
一
步
可
以
走
k
−
1
,
k
,
k
+
1
如果上一步走了k,这一步可以走k-1,k,k+1
如果上一步走了k,这一步可以走k−1,k,k+1
问
最
多
能
得
到
多
少
宝
藏
问最多能得到多少宝藏
问最多能得到多少宝藏
题解:
最
优
解
问
题
,
可
以
考
虑
用
d
p
最优解问题,可以考虑用dp
最优解问题,可以考虑用dp
需
要
维
护
的
是
当
前
位
置
和
上
一
步
走
了
的
步
数
需要维护的是当前位置和上一步走了的步数
需要维护的是当前位置和上一步走了的步数
但
是
想
要
维
护
步
数
这
个
数
就
会
很
大
但是想要维护步数这个数就会很大
但是想要维护步数这个数就会很大
30000
∗
30000
会
导
致
内
存
不
足
30000*30000会导致内存不足
30000∗30000会导致内存不足
但
是
我
们
可
以
发
现
每
次
走
的
步
数
的
是
以
d
为
基
数
的
但是我们可以发现每次走的步数的是以d为基数的
但是我们可以发现每次走的步数的是以d为基数的
这
样
是
一
个
n
2
级
别
的
次
数
就
能
达
到
30000
这样是一个n^2级别的次数就能达到30000
这样是一个n2级别的次数就能达到30000
所
以
我
们
就
考
虑
使
用
一
个
j
所以我们就考虑使用一个j
所以我们就考虑使用一个j
表
示
上
一
次
走
了
d
+
j
的
距
离
表示上一次走了d+j的距离
表示上一次走了d+j的距离
这
样
就
构
造
好
了
d
p
数
组
,
考
虑
转
移
方
程
这样就构造好了dp数组,考虑转移方程
这样就构造好了dp数组,考虑转移方程
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
l
a
s
t
]
[
j
+
k
]
+
a
[
i
]
)
dp[i][j]=max(dp[last][j + k] + a[i])
dp[i][j]=max(dp[last][j+k]+a[i])
l
a
s
t
表
示
转
移
的
位
置
,
k
为
[
−
1
,
1
]
last表示转移的位置,k为[-1,1]
last表示转移的位置,k为[−1,1]
统
计
答
案
即
可
统计答案即可
统计答案即可
AC代码
/*
Author : zzugzx
Lang : C++
Blog : blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
//const int mod = 998244353;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int maxn = 1e6 + 10;
const int N = 3e4 + 5;
const ll inf = 0x3f3f3f3f;
const int dir[][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
int dp[N][510], base = 250;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int n, d;
cin >> n >> d;
for (int i = 1, x; i <= n; i++)
cin >> x, a[x]++;
mem(dp, -inf);
dp[d][base] = a[d];
int ans = 0;
for (int i = 1; i <= 30000; i++)
for (int j = 1; j <= 500; j++) {
int last = i - (d + j - base);
if (last < 0 || last >= i) continue;
for (int k = -1; k <= 1; k++)
if (j + k > 0) dp[i][j] = max(dp[i][j], dp[last][j + k] + a[i]);
ans = max(ans, dp[i][j]);
}
cout << ans;
return 0;
}