A. Mr. Kitayuta, the Treasure Hunter
题意:30001个点,下标为0~30000,有些点有宝藏。你从0往下标大的方向跳,第一步跳的距离为d。如果上一步跳的距离为l,这一步就可以跳l-1或l或l+1(距离必须大于0)。问最多拿到多少宝藏。
思路:dp。dp(i,j)表示当前位置i,上一步距离j能拿到的最大宝藏。但是j如果取0~30000是不行的。计算一下可以发现,1+2+3+...+250>30000。所以我们可以把d映射到250,d-1映射到249......
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <string.h>
#include <algorithm>
using namespace std;
int dp[30010][360];
int gem[30010];
int n,d;
int main(){
memset(dp,-1,sizeof(dp));
cin>>n>>d;
for(int i=1;i<=n;i++){
int p;
scanf("%d",&p);
gem[p]++;
}
int ans=dp[d][250]=gem[d];
for(int i=d;i<=30000;i++){
for(int j=max(1,d-250);j<=d+100;j++){
if(j>i)continue;
int tmp=-1;
tmp=max( tmp , dp[i-j][j-d+250+1] );
tmp=max( tmp , dp[i-j][j-d+250] );
if(j>1)tmp=max( tmp , dp[i-j][j-d+250-1] );
if(tmp!=-1){
dp[i][j-d+250]=tmp+gem[i];
ans=max(ans,dp[i][j-d+250]);
}
}
}
cout<<ans<<endl;
return 0;
}