题意:

给一个初始步长,每次只能跳上次的d+[-1,1]范围内,找最终能取到宝石的最大值

题解

定义个F[i][j]表示在第i个岛屿的最大值,j表示从上一个岛屿走了d+j步到达第i个岛屿
当d=1时,1+2+3...+n<=30000,n最大大概是250,所以最多减少或者增加250步,
即j的范围是[-250,250],为了方便处理下标把j都加上250
last=i-(d+j-250);last代表上一步的岛屿
因为初始岛屿在d处,所以 d<=last<i
记得处理以下初始的答案为 d处的宝石数量,我在这里被卡了好久...
当d=30000并且第30000坐岛屿有宝石时,last=0,循环会进行不下去
F[i][j]=max(f[last][j-1]+a[i],f[last][j]+a[i],f[last][j+1]+a[i])

#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 30005;
int f[maxn][510];
int n,d;
int a[maxn];
int main(){
    cin>>n>>d;
    int b,Max=0;
    memset(a,0,sizeof(a));
    for(int i=1;i<=n;i++){
        cin>>b;
        a[b]++;
        Max=max(Max,b);
    }
    memset(f,-1,sizeof(f));
    f[d][250]=a[d];
    int ans=a[d];//处理一下初始值,有可能步长是30000并且最后一步是30000,这里被卡了好久...
    for(int i=d;i<=Max;i++){//Max为右边界
        for(int j=1;j<=500;j++){
            int last=i-(d+j-250);//last代表上一步的岛屿
            if(last<d || last>=i)continue;//上一步的岛屿坐标不能小于d
            if(f[last][j-1]!=-1){
                f[i][j]=max(f[i][j],f[last][j-1]+a[i]);
            }
            if(f[last][j+1]!=-1){
                f[i][j]=max(f[i][j],f[last][j+1]+a[i]);
            }
            if(f[last][j]!=-1){
                f[i][j]=max(f[i][j],f[last][j]+a[i]);
            }
            ans=max(ans,f[i][j]);
        }
    }
    cout<<ans;
    return 0;
}