您的位置:首页 > 其它

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

2017-04-19 15:59 337 查看
点击打开链接

题意:数轴上点[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
,p
;
int dp
[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;
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: