codeforces 505C - Mr. Kitayuta, the Treasure Hunter(dp)
阿新 • • 發佈:2017-05-20
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 #defineINF 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)