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-250+k>1)//当走到这里的步数大于1时,当前步的上一步有三种可能

  dp[i][j] := max(dp[i-(j+k-250)][j], max(dp[i-(j+k-250)][j-1] , dp[i-(j+k-250)][j+1])) + wei[i];

else//当走到这里的步数等于1时,当前步的上一步只能是1或者2

  dp[i][j] := max(dp[i-(j+k-250)][j],dp[i-(j+k-250)][j+1]) + wei[i];

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define MAX_NUM        60007
#define MAX_STP        509
#define INF   0x3f3f3f3f
int dp[MAX_NUM][MAX_STP];
int wei[MAX_NUM];
int main(int argc, char const *argv[])
{
    int n, k;
    scanf("%d%d",&n,&k);
    int num;
    int ansnum = 0;
    for (int i = 0; i < n ; ++i)
    {
        scanf("%d",&num);
        wei[num]++;
        ansnum = max(ansnum,num);
    }
    memset(dp,-INF,sizeof(dp));
    dp[k][250] = wei[k];
    int ans = wei[k];
    for (int i = k+1; i <= ansnum  ; ++i)
    {
        for (int j = max(1,251-k); j <= 500 ; ++j)
        {
            if(j == 251 - k)
                dp[i][j]  = max(dp[i-(j+k-250)][j],dp[i-(j+k-250)][j+1]) + wei[i];
            else if(i-(j+k-250)>=k){
                dp[i][j] = max(dp[i-(j+k-250)][j], max(dp[i-(j+k-250)][j-1] , dp[i-(j+k-250)][j+1])) + wei[i];
            }
            else
                break;
            ans = max(ans,dp[i][j]);
        }
    }
    printf("%d\n",ans );
    return 0;
}

 

posted @ 2017-05-19 22:21  miamiao  阅读(256)  评论(0编辑  收藏  举报