题意
有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; }