题目链锁: http://codeforces.com/contest/505/problem/C
题意:
有30001个岛,0~30000, 给出n个岛上有宝藏,第一步跳跃距离为d,假设上一步跳跃距离为l,则当前可以跳l-1,l,l+1的距离
dp[i][j]表示在第i个点,上一步的跳跃距离l与第一步的跳跃距离相差为j,即 l = j + d
则
dp[i+l-1][j-1] = max ( dp[i+l-1][j-1], dp[i][j] + cnt[i+l-1] );
dp[i+l][j] = max( dp[l+i][j], dp[i][j] + cnt[i+l] );
dp[i+l+1][j+1] = max( dp[i+l+1][j+1], dp[i][j] + cnt[i+l+1] );
由于 ( d ) + ( d + 1 ) + ( d + 2 ) + ..... + ( d + 250 ) > 251d + 30000 所以取偏移量250;
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<stdio.h> #include<algorithm> #include<cmath> #include<set> #include<map> #include<queue> #include<vector> using namespace std; #define inf 0x3f3f3f3f #define eps 1e-9 #define mod 1000000007 #define FOR(i,s,t) for(int i = s; i < t; ++i ) #define REP(i,s,t) for( int i = s; i <= t; ++i ) #define LL long long #define ULL unsigned long long #define pii pair<int,int> #define MP make_pair #define lson id << 1 , l , m #define rson id << 1 | 1 , m + 1 , r #define maxn ( 30000+10 ) #define maxe ( 200+10 ) int dp[maxn][600], cnt[maxn]; int main () { int n, d; while( cin>>n>>d ) { memset( cnt, 0, sizeof( cnt ) ); for( int i = 0; i < n; ++i ) { int x; scanf("%d", &x ); ++cnt[x]; } memset( dp, -1, sizeof( dp ) ); dp[d][250] = cnt[d]; int ans = cnt[d]; for( int i = d; i <= 30000; ++i ) { for( int j = 0; j <= 500; ++j ) { if( dp[i][j] == -1 ) continue; int l = d + ( j - 250 ); if( l > 0 && i + l <= 30000 ) { dp[i+l][j] = max( dp[l+i][j], dp[i][j] + cnt[i+l] ); ans = max( ans, dp[i+l][j] ); } if( l - 1 > 0 && i + l - 1 <= 30000 ) { dp[i+l-1][j-1] = max( dp[i+l-1][j-1] , dp[i][j] + cnt[i+l-1] ); ans = max( ans, dp[i+l-1][j-1] ); } if( l + 1 <= 30000 && l + 1 > 0 && i + l + 1 <= 30000 ) { dp[i+l+1][j+1] = max( dp[i+l+1][j+1], dp[i][j] + cnt[i+l+1] ); ans = max( ans, dp[i+l+1][j+1] ); } } } printf("%d\n", ans ); } }