Codeforces Round #286 (Div. 2)C

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 - 1l 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.

input
4 10
10
21
27
27
output
   3
题目大意:在一条直线上有若干个宝石,你向右能跳过去,你跳的距离是和上次跳的距离|l1-l2|<=1;问最多能捡多少块宝石。
题目分析:很明显是DP,但是由于姿势见得太少,一道这样的转化一下子状态的题都不会。有很多人一眼看到后多觉得数据太大30000,根本就开不了二维,存不了,深搜的话更没保障。但是!真的需要那么多状态么?其实给定初始跳的距离后这个距离上下波动不会超过300的范围。为什么?简单想想就知道了。1+2+...+300>30000。根本没有那个起点能让你波动到300以外。所以接下来注意点细节,处理下状态转换就行了。

#include <bits/stdc++.h>
using namespace std;
const int INF=(1<<31)-10;
int f[30100],q[30100][610],dp[30100][610];
int main()
{
    int a,d,i,j,n,w,ans;
    scanf("%d%d", &n, &d);///d=300;
    memset(f,0,sizeof(f));
    for (i=0;i<n;i++) {
        scanf("%d", &a);f[a]++;
    }
    memset(q,0,sizeof(q));
    memset(dp,0,sizeof(dp));
    dp[d][300]+=f[d];q[d][300]=1;ans=dp[d][300];
    for (i=d+1;i<=30000;i++)
        for (j=20;j<=580;j++) {
        w=j+d-300;
        if (i>=w&&w>0&&q[i-w][j-1]) {
            dp[i][j]=max(dp[i][j],dp[i-w][j-1]+f[i]);
            q[i][j]=1;
        }
        if (i>=w&&w>0&&q[i-w][j]) {
            dp[i][j]=max(dp[i][j],dp[i-w][j]+f[i]);
            q[i][j]=1;
        }
        if (i>=w&&w>0&&q[i-w][j+1]) {
            dp[i][j]=max(dp[i][j],dp[i-w][j+1]+f[i]);
            q[i][j]=1;
        }
        if (dp[i][j]>ans) ans=dp[i][j];
        }
    printf("%d\n", ans);
    return 0;
}


你可能感兴趣的:(Codeforces Round #286 (Div. 2)C)