题意
有30000个岛屿,某些岛屿上有一些宝石,第一次跳到了d号岛上,每次跳跃的距离与上一次跳跃的距离之差不超过1,问你最多可以收集多少宝石。
分析
我们可以定义 dp[i][j] 表示为跳到第 i 个岛屿,且上一次跳跃距离为 j ,那么显然有
但是这样做,显然时间和空间都不够。
我们可以发现,第一步和最后一步的差值不会超过 250 ,因为1+2+3+...+250 > 30000
那么我们可以定义 dp[i][j] 表示跳到第 i 个岛屿,且与第一次跳跃距离的差值为 j-250 。
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;
const int maxn = 30010;
const int M = 1e9+7;
int n,m,d;
int a[maxn],dp[maxn][550]; //到第i个岛,上一步走了d+(j-250)远
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);
cin>>n>>d;
for(int i = 1,x; i <= n; i++)
{
cin>>x;
a[x]++;
m = max(m,x);
}
mem(dp,-1);dp[d][250] = a[d];
int ans = a[d];
for(int i = d; i <= m; i++)
{
for(int j = 1; j <= 500;j++)
{
if(dp[i][j] == -1) continue;
int to = i+d+j-250;
//l
if(to > i && to <= 30000)
{
dp[to][j] = max(dp[to][j],dp[i][j]+a[to]);
ans = max(ans,dp[to][j]);
}
//l-1
if(to-1 > i && to-1 <= 30000)
{
dp[to-1][j-1] = max(dp[to-1][j-1],dp[i][j]+a[to-1]);
ans = max(ans,dp[to-1][j-1]);
}
//l+1
if(to+1 > i && to+1 <= 30000)
{
dp[to+1][j+1] = max(dp[to+1][j+1],dp[i][j]+a[to+1]);
ans = max(ans,dp[to+1][j+1]);
}
}
}
cout<<ans<<endl;
return 0;
} 
京公网安备 11010502036488号