很容易想到dp,但是直接dp的话,30000*30000的空间开不下。
可以采用跳跃步数和d的偏差量的方法。由于偏差量不超过250,因此第二维可以储存偏差量,而非每次的步数。
偏差量不超过250很好证明。若超过了,则必然已经调到30000以外了。
#include<bits/stdc++.h>
using namespace std;
int val[30030],dp[30030][610];
int main()
{
int n,d,i,j,k,next,p,ans,nmax;
while(cin>>n>>d)
{
memset(val,0,sizeof(val));
for(i=0;i<n;i++)
{
scanf("%d",&p);
val[p]++;
}
nmax=p;
memset(dp,-1,sizeof(dp));
dp[d][300]=val[d];
for(i=d;i<=nmax;i++)
{
for(j=0;j<=600;j++)
{
if(dp[i][j]>=0)
{
next=d+j-300;
for(k=-1;k<=1;k++)
{
if(next+k>=1&&i+next+k<=nmax)
dp[i+next+k][j+k]=max(dp[i+next+k][j+k],dp[i][j]+val[i+next+k]);
}
}
}
}
ans=0;
for(i=d;i<=nmax;i++)
for(j=0;j<=600;j++)
ans=max(ans,dp[i][j]);
printf("%d\n",ans);
}
}