您的位置:首页 > 其它

cf#186-C. Mr. Kitayuta, the Treasure Hunter-dp(预推断+offset)

2016-03-08 21:56 393 查看
http://codeforces.com/problemset/problem/505/C

题意:

有30001个岛屿,下标为0~30000,给n个数告诉你有n份宝藏藏在哪些岛上。 

你从0往下标大的方向跳,第一步跳的距离为d。

如果上一步跳的距离为D,这一步就可以跳D-1或D或D+1(但是距离必须大于0)。

问最多拿到多少宝藏。

思路:

dp[i][j] 表示 刚到达第i岛屿,从上一岛屿跳过来的步长是D+j单位距离 ,

那么我们可以推得三种后继情况

int dis=i+D+j,  

1·  这一步选择仍跳D+j距离,则dp[dis][j]=max(dp[dis][j],dp[i][j]+vis[dis]);

2·  这一步选择跳D+j+1距离,则dp[dis+1][j+1]=max(dp[dis+1][j+1],dp[i][j]+vis[dis+1]);

3·  这一步选择跳D+j-1距离,则dp[dis-1][j-1]=max(itself,dp[i][j]+vis[dis-1]);

注意每一步要判断即将到达的位置是否<=30000

初始化dp数组为-1,要递推的话肯定是从第0个岛屿推起,也就是初始化dp[D][0]=vis[D]   // 其实是dp[D][250]=vis[250];

因为len=30000,并且每次步长最多递增1,1+2+3+...+n=n*(n+1)/2<=30000,

n最多不超过250, 也就是最长的步长不会超过D+250,

当然如果每次递减1,最短的步长也不会少于D-250

所以我们枚举的 的j,只需要从-250到250,显然数组下标为负数不方便,我们加250的offset,把j变成0~500,

而每次 从上一岛屿跳过来的步长就变成了D+j-250

在递推过程中,第三种情况要注意加判断,因为第三种是步长不断减小,可能减成负数了。。。我们令dis-1>i,即距离差为正即可

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001;
int max(int a,int b)
{return a<b?b:a;}
int max(int a,int b,int c)
{return max(a,max(b,c));}
int vis[30005];
int dp[30005][520];
int main()
{
//vis[i] //第i岛屿的gem数
//dp[i][j] //到达第i处, 此时走j步,收集到的gem
int n,D;
cin>>n>>D;
int i,j,tmp;
memset(dp,-1,sizeof(dp)); //初始化为-1
for (i=1;i<=n;i++)
{
scanf("%d",&tmp);
vis[tmp]++;
}
int maxx=vis[D];
dp[D][250]=vis[D];

for (i=D;i<=30000;i++)
{
for (j=1;j<=500;j++)
{
if (dp[i][j]==-1)continue;
int dis=i+D+j-250;
if (dis<=30000)
{
dp[dis][j]=max(dp[dis][j],dp[i][j]+vis[dis]);
maxx=max(maxx,dp[dis][j]);
}
if (dis+1<=30000)
{
dp[dis+1][j+1]=max(dp[dis+1][j+1],dp[i][j]+vis[dis+1]);
maxx=max(maxx,dp[dis+1][j+1]);
}
if (dis-1>i&&dis-1<=30000)//要求步长为正数,即dis-1>i
{
dp[dis-1][j-1]=max(dp[dis-1][j-1],dp[i][j]+vis[dis-1]);
maxx=max(maxx,dp[dis-1][j-1]);
}
}
}
printf("%d\n",maxx);

return 0;

}

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: