跳跃

C 跳跃
文件名 输入文件 输出文件 时间限制 空间限制
jump.cpp/c/pas jump.in jump.out 1s 512MB
题目描述
美丽国有 n 座小岛。这些小岛排成了一条直线,依次编号为 0,1,2,3... 有的小岛
上有金块,有的小岛上没有。美丽国有一个巨人 Bob,有一天他决定从第 0 个岛开
始,一直往后跳,看看自己能收集多少金块。
当然,Bob 不是没有目的性的乱跳;相反,Bob 的跳跃要满足以下规则:
• 首先 Bob 从 0 跳到 d 岛屿
• 假如 Bob 上一次跳了 l 步,则 Bob 下一次可以选择跳 l、l − 1、l + 1 步。注
意:所跳的步数不能小于 1,即如果上一次跳跃的步数为 1,下一次跳跃的步
数只能是 1 或者 2。
在这样的规则下,Bob 想知道,他最多能拿到多少金块?
输入格式
输入第一行两个整数 n,d,分别表示有金块的岛屿的个数,和 Bob 第一步要
跳的步数。
接下来 n 行,每行一个整数 id,表示编号为 id 的岛屿上有金块。
输出格式
输出仅一行,表示 Bob 最多能收集多少金块。
样例输入 1
4 10
10
21
27
27
6
样例输出 1
3
样例输入 2
8 8
9
19
28
36
45
55
66
78
样例输出 2
6
数据范围
对于 30% 的数据,1 ≤ n,d,id ≤ 100
对于 70% 的数据,1 ≤ n,d,id ≤ 1000
对于 100% 的数据,1 ≤ n,d,id ≤ 30000

我首先写了个记忆化搜索,想写dp但是不会写啊。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int maxn;
int n,d;
int w[2009];
int ans;
int f[1009][1009];
int dfs(int x,int tot,int last)
{
    if(x>maxn)
    {
        ans=max(ans,tot);
        return tot;
    }
    if(f[x][last])    return f[x][last];//后面的都搜过就不搜了
    
    for(int i=max(1,last-1);i<=last+1;i++)
        f[x][last]=max(f[x][last],dfs(x+i,tot+w[x+i],i));
    return tot;
}
int main()
{
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    scanf("%d%d",&n,&d);
    for(int i=1,x;i<=n;i++)
    {
        scanf("%d",&x);
        w[x]++;maxn=max(maxn,x);
    }
    dfs(d,w[d],d);
    cout<<ans;
    return 0;
}

dp从后向前搜,f[i][j]表示当前在位置i,接下来走j步,回溯回来能拿多少金币。

  转移方程是

  f[i][j]=a[i]+max(f[i+j][j],f[i+j][j+1],f[i+j][j-1]).

[#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int maxn;
int n,d;
int w[2009];
int ans;
int f[1009][1009];
int dfs(int x,int tot,int last)
{
    if(x>maxn)
    {
        ans=max(ans,tot);
        return tot;
    }
    if(f[x][last])    return f[x][last];
    
    for(int i=max(1,last-1);i<=last+1;i++)
        f[x][last]=max(f[x][last],dfs(x+i,tot+w[x+i],i));
    return tot;
}
int main()
{
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    scanf("%d%d",&n,&d);
    for(int i=1,x;i<=n;i++)
    {
        scanf("%d",&x);
        w[x]++;maxn=max(maxn,x);
    }
    dfs(d,w[d],d);
    cout<<ans;
    return 0;
}

 

posted @ 2017-10-24 17:43  浪矢-CL  阅读(212)  评论(0编辑  收藏  举报