题意:
有一个由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;
}
京公网安备 11010502036488号