朴素的思路就是二维dp,表示上次跳了几个
但是这个存不下,又因为题目提示我们第一次一定是D
因此我们第二维表示上次移动了D+j次,这是因为j只要移动250,就能到达终点,因此可以存下
但是可能是负数,因此我们使用坐标系平移
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=1e5+10; int base=250; int f[30010][510]; int a[N]; int main(){ ios::sync_with_stdio(false); int n,d; cin>>n>>d; int i,j; for(i=1;i<=n;i++){ int x; cin>>x; a[x]++; } memset(f,-0x3f,sizeof f); f[d][base]=a[d]; int ans=0; ans=a[d]; for(i=d+1;i<=30000;i++){ for(j=0;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){ f[i][j]=max(f[i][j],f[last][j+k]+a[i]); } } ans=max(ans,f[i][j]); } } cout<<ans<<endl; return 0; }