NOIP 模拟题 跳跃

来源:互联网 发布:帝国时代2非洲王朝mac 编辑:程序博客网 时间:2024/05/21 10:24

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

先打了普通dfs,连第二个样例都跑不出来。
然后打了记忆化搜索,70分。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define LL long longusing namespace std;const int N=1009;int n,k,a[N],ans,maxn,s[N];int f[2*N][2*N];int dfs(int x,int dis){    if(x>maxn) return 0;    int tot=0;    tot=max(tot,f[x+dis][dis]?f[x+dis][dis]:f[x+dis][dis]=dfs(x+dis,dis));    tot=max(tot,f[x+dis+1][dis+1]?f[x+dis+1][dis+1]:f[x+dis+1][dis+1]=dfs(x+dis+1,dis+1));    if(dis>1)    tot=max(tot,f[x+dis-1][dis-1]?f[x+dis-1][dis-1]:f[x+dis-1][dis-1]=dfs(x+dis-1,dis-1));    return f[x][dis]=tot+a[x];}int main(){    freopen("jump.in","r",stdin);    freopen("jump.out","w",stdout);    scanf("%d%d",&n,&k);    for(int x,i=1;i<=n;i++)     {        scanf("%d",&x);        a[x]++;        maxn=max(maxn,x);    }    for(int i=maxn;i>=1;i--) s[i]=s[i+1]+a[i];    ans=dfs(k,k);    printf("%d",ans);    return 0;}
原创粉丝点击