题解:
也是参考了网上大佬的解法才会的
dp[i][j]表示到达第i岛屿,从上一岛屿跳过来的步长是D+j单位距离
那么将会有三种递推情况
1.这一步跳D+j的距离
2.这一步跳D+j+1的距离
3.这一步跳D+j-1的距离
分别对应图上三个if
为什么n最大只有250
因为len=30000,并且每次步长最多递增1,1+2+3+...+n=n*(n+1)/2<=30000,
n最多不超过250, 所以最长的步长不会超过D+250
但是如果每次都-1的话,数组下标就成了负数了,所以这里把起点设置为250,就消除了负数的影响。

代码:

/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
const int maxn = 3e4+10;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;

int visited[maxn];
int dp[maxn][510];
int main(){
    int n,d;
    cin>>n>>d;
    memset(dp,-1,sizeof dp);
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        visited[x]++;
    }
    int imax=visited[d];
    dp[d][250]=visited[d];
    for(int i=d;i<=30000;i++){
        for(int j=1;j<=500;j++){
            if(dp[i][j]==-1) continue;
            int pos=i+d+j-250;
            if(pos<=30000){
                dp[pos][j]=max(dp[pos][j],dp[i][j]+visited[pos]);
                imax=max(imax,dp[pos][j]);
            }
            if(pos+1<=30000){
                dp[pos+1][j+1]=max(dp[pos+1][j+1],dp[i][j]+visited[pos+1]);
                imax=max(imax,dp[pos+1][j+1]);
            }
            if(pos-1>i&&pos-1<=30000){
                dp[pos-1][j-1]=max(dp[pos-1][j-1],dp[i][j]+visited[pos-1]);
                imax=max(imax,dp[pos-1][j-1]);
            }
        }
    }
    cout<<imax<<endl;
    return 0;

}