codeforces #286 div2 C(DP)
2015-01-19 01:23:28
思路:嘛...其实只要发现d的变化范围不超过300(准确来说只要使1+2+3+....+k>30000,k就是范围)就行了。
用记忆化搜索,其中一个参数是d偏离最开始的值的大小。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=1;i<=(n);++i) 17 #define REV(i,n) for(int i=(n);i>=1;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define MP(a,b) make_pair(a,b) 21 22 typedef long long ll; 23 typedef pair<int,int> pii; 24 const int INF = (1 << 30) - 1; 25 const int maxn = 30010; 26 27 int n,d,cur,tmax,num[maxn]; 28 int dp[maxn][1000]; 29 30 int Dfs(int p,int pre){ 31 if(p > tmax) return 0; 32 if(dp[p][pre - d + 400] != -1) return dp[p][pre - d + 400]; 33 int res = 0; 34 if(pre > 1) res = max(res,Dfs(p + pre - 1,pre - 1)); 35 res = max(res,Dfs(p + pre,pre)); 36 res = max(res,Dfs(p + pre + 1,pre + 1)); 37 return dp[p][pre - d + 400] = res + num[p]; 38 } 39 40 int main(){ 41 int a; 42 MEM(dp,-1); 43 scanf("%d%d",&n,&d); 44 REP(i,n){ 45 scanf("%d",&a); 46 num[a]++; 47 tmax = max(tmax,a); 48 } 49 printf("%d\n",Dfs(d,d)); 50 return 0; 51 }