Codeforces Round #286 (Div. 2) C. Mr. Kitayuta, the Treasure Hunter+dp+优化

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;
}
时间: 2024-10-09 08:36:13

Codeforces Round #286 (Div. 2) C. Mr. Kitayuta, the Treasure Hunter+dp+优化的相关文章

Codeforces Round #286 (Div. 1) A. Mr. Kitayuta, the Treasure Hunter DP

链接: http://codeforces.com/problemset/problem/506/A 题意: 给出30000个岛,有n个宝石分布在上面,第一步到d位置,每次走的距离与上一步的差距不大于1,问走完一路最多捡到多少块宝石. 题解: 容易想到DP,dp[i][j]表示到达 i 处,现在步长为 j 时最多收集到的财富,转移也不难,cnt[i]表示 i 处的财富. dp[i+step-1] = max(dp[i+step-1],dp[i][j]+cnt[i+step+1]) dp[i+st

Codeforces Round #286 (Div. 2)B. Mr. Kitayuta&#39;s Colorful Graph(dfs,暴力)

数据规模小,所以就暴力枚举每一种颜色的边就行了. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm>

Codeforces Round #286 (Div. 2)A. Mr. Kitayuta&#39;s Gift(暴力,string的应用)

由于字符串的长度很短,所以就暴力枚举每一个空每一个字母,出现行的就输出.这么简单的思路我居然没想到,临场想了很多,以为有什么技巧,越想越迷...是思维方式有问题,遇到问题先分析最简单粗暴的办法,然后一步一步的优化,不能盲目的想. 这道题要AC的快需要熟悉string的各种用法.这里做个简单总结:C++中string的常见用法. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstrin

Codeforces Round #286 (Div. 2) B. Mr. Kitayuta&#39;s Colorful Graph +foyd算法的应用

B. Mr. Kitayuta's Colorful Graph time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the g

水题 Codeforces Round #286 (Div. 2) A Mr. Kitayuta&#39;s Gift

题目传送门 1 /* 2 水题:vector容器实现插入操作,暴力进行判断是否为回文串 3 */ 4 #include <cstdio> 5 #include <iostream> 6 #include <algorithm> 7 #include <cstring> 8 #include <string> 9 #include <vector> 10 using namespace std; 11 12 const int MAXN

DFS/并查集 Codeforces Round #286 (Div. 2) B - Mr. Kitayuta&#39;s Colorful Graph

题目传送门 1 /* 2 题意:两点之间有不同颜色的线连通,问两点间单一颜色连通的路径有几条 3 DFS:暴力每个颜色,以u走到v为结束标志,累加条数 4 注意:无向图 5 */ 6 #include <cstdio> 7 #include <iostream> 8 #include <algorithm> 9 #include <cstring> 10 #include <string> 11 #include <vector> 1

Codeforces Round #286 (Div. 1) D. Mr. Kitayuta&#39;s Colorful Graph

D - Mr. Kitayuta's Colorful Graph 思路:我是暴力搞过去没有将答案离线,感觉将答案的离线的方法很巧妙.. 对于一个不大于sqrt(n) 的块,我们n^2暴力枚举, 对于大于sqrt(n)的块,我们暴力枚举答案. 这样就能做到严格sqrt(n) * n #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #defin

codeforces 505C - Mr. Kitayuta, the Treasure Hunter(dp)

题意 一共有30000个位置,从第0个位置开始走,第一次走k步,对于每一次走步,可以走上一次的ki+1 ,ki ,ki-1步数(必须大于等于1),每个岛上有value,求最大能得到的value能有多少. 分析 一开始我想用搜索做,然后一直会T,看了题解才知道是用dp来做,感觉最后自己还是写的挺搓的_(:з」∠)_. 首先可以证明出每一步的步数与第一次的步数差值不会超过250. 开一个二维dp数组,dp[i][j]代表在第i个位置,前一步走了(j-250+k)步数 所以dp转移方程为 if(j-2

Codeforces Round #286 div.1 D 506D D. Mr. Kitayuta&#39;s Colorful Graph【并查集】

题目链接:http://codeforces.com/problemset/problem/506/D 题目大意: 给出n个顶点,m条边,每条边上有一个数字,代表某个颜色.不同数字代表不同的颜色.有很多个询问,每个询问问有多少条纯种颜色的路径使得某两个点联通. 分析: 这个题一看就想用并查集来搞,每种颜色用一个并查集处理.对于输入的每条边,我们只需要将这两个点在这条边的颜色对应的并查集中合并就好了.查询的时候,我们只需要检测这两个点在多少个颜色对应的并查集中是在统一集合中的,那么就有多少条纯种颜