C. Mr. Kitayuta, the Treasure Hunter
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
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.
Input
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.
Output
Print the maximum number of gems that Mr. Kitayuta can collect.
Sample test(s)
input
4 10 10 21 27 27
output
3
input
8 8 9 19 28 36 45 55 66 78
output
6
input
13 7 8 8 9 16 17 17 18 21 23 24 24 26 30
output
4
Note
In the first sample, the optimal route is 0 ?→? 10 (+1 gem) ?→? 19 ?→? 27
(+2 gems) ?→?...
In the second sample, the optimal route is 0 ?→? 8 ?→? 15 ?→? 21?→? 28
(+1 gem) ?→? 36 (+1 gem) ?→? 45 (+1 gem) ?→? 55
(+1 gem) ?→? 66 (+1 gem) ?→? 78 (+1 gem) ?→?...
In the third sample, the optimal route is 0 ?→? 7 ?→? 13 ?→? 18
(+1 gem) ?→? 24 (+2 gems) ?→? 30 (+1 gem) ?→?...
解决方案:此题我已开始从前往后dp,发现了一个严重的错误,它并不能快速求出以d为起点的最优路径,应该从后往前dp。设dp[i][j],i为位置,j为从前一个位置跳到i的步长。从后往前dp如下 :
dp[i][j]=0当i大于n(总的岛的编号)
dp[i][j]=i岛获得的珠宝+max(dp[i+j][j],dp[i+j+1][j+1])当j==1&&i<=n
dp[i][j]=i岛获得的珠宝+max(dp[i+j][j],dp[i+j+1][j+1],dp[i+j-1][j-1])当j>1&&i<=n
但是这样还不行,开不了n^2那么大的组,时间复杂的也是n^2,会爆内存,所以必须优化维度。
若每一步以d+1的步长走,则总的步长为:d+1+d+2+d+3+.......+d+245>=1+.....+245=?245·(245?+?1)?/?2?=?30135?>?30000
所以最多会小于d+245步长
若d>245每一步以d-1的步长走,则总的步长为:d?+?(d?-?1)?+?(d?-?2)?+?...?+?(d?-?245)?≥?245?+?244?+?...?+?1?=?245·(245?+?1)?/?2?=?30135?>?30000
所走的步长大于d-245
所以范围是d-245到d+245之间,至于d<245的最小步长是1。有了这些规律,我们的数组可以开的比较小dp[30003][600]。
code:
#include <iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int dp[60603][600]; int score[30003]; int Max; int main() { int n,d; while(~scanf("%d%d",&n,&d)) { memset(score,0,sizeof(score)); for(int i=0; i<n; i++) { int p; scanf("%d",&p); score[p]++; } memset(dp,0,sizeof(dp)); Max=0; int mm=sqrt(2*30000); int st,offset; if(d-mm<=0) { st=1; offset=0; } else { st=d-mm; offset=d-mm-1; } for(int i=30000; i>=d; i--) { for(int j=st; j<=d+mm; j++) { if(j-1==0) dp[i][j-offset]=score[i]+max(dp[i+j][j-offset],dp[i+j+1][j-offset+1]); if(j-1>=1) dp[i][j-offset]=score[i]+max(dp[i+j+1][j-offset+1],max(dp[i+j][j-offset],dp[i+j-1][j-offset-1])); } } printf("%d\n",dp[d][d-offset]); } return 0; }