题意:
有一个由30001个小岛组成的群岛,编号为0-30000,一字排开,首先从0岛跳的d岛,然后每一次跳的距离与上一次的距离绝对值等于小于1,有些岛有宝石。

思路:
dp:
ma[i]表示i岛的宝石数目。
dp[i][j]表示跳到i时跳的距离为250-j+d时收集的最大宝石数。
初始化dp[d][250]=ma[d].
s=250-j+d;
dp[i][j]=max(dp[i][j],dp[i-s][j]+ma[i])
dp[i][j]=max(dp[i][j],dp[i-s][j+1]+ma[i])
dp[i][j]=max(dp[i][j],dp[i-s][j-1]+ma[i])(s>=2(因为这一步为1时它的前一步为0(0不符合条件)))。

代码:

#include <bits/stdc++.h>
typedef long long ll;

using namespace std;

const ll inf=998244353;

inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

int ma[100005], dp[30005][505];

int main()
{
    int n, d;
    scanf("%d%d",&n,&d);
    fill(dp[0],dp[0]+30005*505,-inf);
    for(int i=1; i<=n; i++)
    {
        int x;
        scanf("%d",&x);
        ma[x]++;
    }
    dp[d][250]=ma[d];
    int ans=ma[d];
    for(int i=d+1;i<=30001;i++)
    {
        for(int j=1;j<=500;j++)
        {
            int s=j-250+d;
            if(s>=1&&i-s>=d)
            {
                dp[i][j]=max(dp[i][j],ma[i]+dp[i-s][j+1]);
                dp[i][j]=max(dp[i][j],ma[i]+dp[i-s][j]);
                if(s>=2)
                dp[i][j]=max(dp[i][j],ma[i]+dp[i-s][j-1]);
            }
            ans=max(ans,dp[i][j]);
        }
    }
    printf("%d\n",ans);
    return 0;
}