标签:
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:
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 10 10 21 27 27
3
8 8 9 19 28 36 45 55 66 78
6
13 7 8 8 9 16 17 17 18 21 23 24 24 26 30
4
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; }
Codeforces Round #286 (Div. 2) C. Mr. Kitayuta, the Treasure Hunter+dp+优化
标签:
原文地址:http://blog.csdn.net/u012870383/article/details/43016023