Codeforces 505C Mr. Kitayuta, the Treasure Hunter DP+技巧优化

来源:互联网 发布:13.3英寸笔记本知乎 编辑:程序博客网 时间:2024/03/29 07:53

点击打开链接

题意:数轴上点[0, 30000]。先从 0 跳到 d<=3e4  以后每次跳的步数是 {prev-1, prev, prev+1}。跳得步数必须>=1,跳到某个点上可以得到相应的value,求可以得到最大的value。

明显DP阿,设dp[i][j] 当前在i,上一次跳跃距离为j,dp[i][j]=max(dp[i+j][j],dp[i+j+1][j+1],dp[i+j-1][j-1])+val[i];

i,j<=3e4 爆空间了,直觉:每次所在点都是递增的,没有那么多状态 用map水一发,结果TLE (卡STL了,差一点)

考虑最坏的情况 起点为0,任意给d d每次+1 最大可以变化到 d+k 则 (k+1)(d+d+k)/2<=3e4 k<=sqrt(2*M)  最小变化也是一样

则d 最多变化sqrt(M)次 状态最多也只有O(Msqrt(M)个 每次转移O(1),把d映射成sqrt(M) 记忆化DP即可

#include <bits/stdc++.h>using namespace std;const int N=3e4+20;const int M=3e4;int n,d,mx,ans,cnt=0,b;int val[N],p[N];int dp[N][1200];//dp[i][j] 当前在i上一次跳跃距离为j //j的转移不会超过sqrt(M),j映射sqrt(M)  int DP(int i,int j,int k)//j->k{if(dp[i][k]!=-1)return dp[i][k];dp[i][k]=val[i];int res=0;if(i+j<=mx)res=max(res,DP(i+j,j,k));if(i+j+1<=mx)res=max(res,DP(i+j+1,j+1,k+1));if(i+j-1<=mx&&j-1>=1)res=max(res,DP(i+j-1,j-1,k-1));dp[i][k]+=res;return dp[i][k];}int main(){while(cin>>n>>d){memset(p,0,sizeof(p));mx=ans=0;int x;memset(dp,-1,sizeof(dp));memset(val,0,sizeof(val));for(int i=0;i<n;i++)scanf("%d",&x),val[x]++,mx=max(mx,x);b=2*(int)sqrt(M);ans=DP(d,d,b);printf("%d\n",ans);}return 0;}



 


0 0