题意:
给一个初始步长,每次只能跳上次的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; }