codeforces 505C Mr. Kitayuta, the Treasure Hunter(dp)
来源:互联网 发布:巨人网络招聘 编辑:程序博客网 时间:2024/04/29 22:00
题目链接
The Shuseki Islands are an archipelago of 30001 small islands in the Yutampo Sea. The islands are evenly spaced along a line, numbered from 0 to 30000 from the west to the east. These islands are known to contain many treasures. There are n gems in the Shuseki Islands in total, and the i-th gem is located on island pi.
Mr. Kitayuta has just arrived at island 0. With his great jumping ability, he will repeatedly perform jumps between islands to the east according to the following process:
- First, he will jump from island 0 to island d.
- After that, he will continue jumping according to the following rule. Let l be the length of the previous jump, that is, if his previous jump was from island prev to island cur, let l = cur - prev. He will perform a jump of length l - 1, l or l + 1 to the east. That is, he will jump to island (cur + l - 1), (cur + l) or (cur + l + 1) (if they exist). The length of a jump must be positive, that is, he cannot perform a jump of length 0 when l = 1. If there is no valid destination, he will stop jumping.
Mr. Kitayuta will collect the gems on the islands visited during the process. Find the maximum number of gems that he can collect.
The first line of the input contains two space-separated integers n and d (1 ≤ n, d ≤ 30000), denoting the number of the gems in the Shuseki Islands and the length of the Mr. Kitayuta's first jump, respectively.
The next n lines describe the location of the gems. The i-th of them (1 ≤ i ≤ n) contains a integer pi (d ≤ p1 ≤ p2 ≤ ... ≤ pn ≤ 30000), denoting the number of the island that contains the i-th gem.
Print the maximum number of gems that Mr. Kitayuta can collect.
4 1010212727
3
8 8919283645556678
6
13 788916171718212324242630
4
题意:有30001个岛,在一条线上,从左到右编号一次为0到30000。某些岛屿上有些宝石。初始的时候有个人在岛屿0,他将跳到岛屿d,他跳跃的距离为d。如果当前他跳跃的距离为L,他下一次跳跃的距离只能为L-1,L,L+1之一且不能为0。他只能往编号更大的岛跳,直到他不能跳,问他最多能收集多少个宝石?
题解:很容易想到dp,用dp[i][j] 表示当前在岛屿i,上一次跳跃的距离为j,最多能收集多少个宝石。但是这样无论空间还是时间都不能接受。我们可以发现,他跳跃的距离L不会超过d+250,因为1+2+3+...250>30000。有了这个性质,我们就可以用dp[i][j]表示当前在岛屿i,上一次跳跃的距离为d+j,该状态下他最多能收集多少个宝石?
空间复杂度和时间复杂度都为O(n*sqrt(n))。
代码如下:
#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>#include<string>#include<queue>#include<stack>#include<map>#include<set>#include<stdlib.h>#include<vector>#define inff 0x3fffffff#define nn 110000#define mod 1000000007typedef long long LL;const LL inf64=inff*(LL)inff;using namespace std;int n,d;int num[31000];int dp[31000][510];int main(){ int i,x,j; while(scanf("%d%d",&n,&d)!=EOF) { memset(num,0,sizeof(num)); for(i=1;i<=n;i++) { scanf("%d",&x); num[x]++; } memset(dp,-1,sizeof(dp)); dp[d][250]=num[d]; int ans=0; for(i=d;i<=30000;i++) { for(j=0;j<=500;j++) { if(dp[i][j]!=-1) { ans=max(dp[i][j],ans); if(i+d+j-250<=30000) dp[i+d+j-250][j]=max(dp[i+d+j-250][j],dp[i][j]+num[i+d+j-250]); if(i+d+j-1-250<=30000&&d+j-250-1) dp[i+d+j-251][j-1]=max(dp[i+d+j-251][j-1],dp[i][j]+num[i+d+j-251]); if(i+d+j+1-250<=30000) dp[i+d+j+1-250][j+1]=max(dp[i+d+j+1-250][j+1],dp[i][j]+num[i+d+j+1-250]); } } } printf("%d\n",ans); } return 0;}比赛的时候我没有想到正解,但是知道有效状态数不会太多,所以使用记忆化搜索写过的,当然还要到hash。
复杂度为O(10^7),代码如下:
#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>#include<string>#include<queue>#include<stack>#include<map>#include<set>#include<stdlib.h>#include<vector>#define inff 0x3fffffff#define nn 21000#define mod 20000009typedef long long LL;const LL inf64=inff*(LL)inff;using namespace std;int n,d;int num[3*nn];int sum[3*nn];int mxid;int ha[nn*1000];int hashx(int x,int y){ int ix=x+30007*y; int key=ix%mod; int i; for(i=key;;i=(i+1)%mod) { if(ha[i]==-1) { ha[i]=ix; break; } else if(ha[i]==ix) break; } return i;}int dp[nn*1000];int dfs(int id,int l){ if(l==1||l==2) return sum[mxid]-sum[id-1]; int ix=hashx(id,l); if(dp[ix]!=-1) return dp[ix]; int re=0; if(id+l<=mxid) re=max(re,dfs(id+l,l)); if(id+l-1<=mxid&&l-1>0) re=max(re,dfs(id+l-1,l-1)); if(id+l+1<=mxid) re=max(re,dfs(id+l+1,l+1)); return dp[ix]=re+num[id];}int main(){ int i,x; while(scanf("%d%d",&n,&d)!=EOF) { memset(num,0,sizeof(num)); memset(ha,-1,sizeof(ha)); memset(dp,-1,sizeof(dp)); sum[0]=0; for(i=1;i<=n;i++) { scanf("%d",&x); num[x]++; mxid=x; } for(i=1;i<=mxid;i++) { sum[i]=sum[i-1]+num[i]; } if(d==1||d==2) printf("%d\n",n); else printf("%d\n",dfs(d,d)); } return 0;}
- codeforces 505C Mr. Kitayuta, the Treasure Hunter(dp)
- codeforces 505C C. Mr. Kitayuta, the Treasure Hunter (dp)
- codeforces 505C Mr. Kitayuta, the Treasure Hunter(DP)
- codeforces 505C Mr. Kitayuta, the Treasure Hunter(DP)
- Codeforces Round #286 C. Mr. Kitayuta, the Treasure Hunter dp
- CodeForces 505C Mr. Kitayuta, the Treasure Hunter
- CodeForces-505C Mr. Kitayuta, the Treasure Hunter
- codeforces 505C Mr. Kitayuta, the Treasure Hunter
- codeforces 505C Mr. Kitayuta, the Treasure Hunter( dp 缩减规模 )
- Codeforces 505C Mr. Kitayuta, the Treasure Hunter DP+技巧优化
- Codeforces Round #286 (Div. 2) C. Mr. Kitayuta, the Treasure Hunter(经典的DP)
- CodeForces #505C# Mr. Kitayuta, the Treasure Hunter(dp数组定义)
- 【DP】 Codeforces Round #286 A - Mr. Kitayuta, the Treasure Hunter
- dp cf C. Mr. Kitayuta, the Treasure Hunter
- cf286C Mr. Kitayuta, the Treasure Hunter dp
- dp Codeforces505C Mr. Kitayuta, the Treasure Hunter
- Codeforces Round #286 (Div. 2) C. Mr. Kitayuta, the Treasure Hunter——dp
- Codeforces Round #286 (Div. 2) C. Mr. Kitayuta, the Treasure Hunter+dp+优化
- [计算机英语每日翻译] The Linux Kernel (LInux内核原理解析)1
- Hudsonbld持续集成平台-集成任务四大执行模式
- MATLAB数据溢出
- 树的建立与遍历--递归
- Java---20---多线程:生产者和消费者2(JDK1.5升级版)
- codeforces 505C Mr. Kitayuta, the Treasure Hunter(dp)
- 【BZOJ3039】玉蟾宫/【HDU1505】【POJ1964】City Game 最大01子矩阵
- Android 修改输入法的输入语言
- logback.xml配置
- 基于lucene的案例开发:搜索索引
- python 生成随机字符串
- 三款常用的Java字节码反编译工具
- 写完博客,发表时为什么要输入验证码?
- 那里学软件开发好