1. 程式人生 > >codeforces 505C - Mr. Kitayuta, the Treasure Hunter(dp)

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

tdi -i == cst pri cstring set div ++

題意


一共有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; }

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