题意:
有一个由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; }