Codeforces Round #286 (Div. 2) C Mr. Kitayuta, the Treasure Hunter ( DP )

题目链锁: 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 ); 
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值