Codeforces 505C

Mr. Kitayuta, the Treasure Hunter

题意:有n个宝藏分部在n个岛屿上,现在给出n个岛屿的位置,初始的时候你从0位置跳到位置为d的岛屿,往后每次跳跃的步长只能是上pre+1 pre pre-1 这3种(pre表示上一步的步长)

思路:dp+技巧优化空间

  dp式很容易想到,dp[i][j]表示当前在第i个岛屿,上一步跳的步长为j,这样就得开3e4*3e4的数组,显然要爆内存,但是推一下很容易知道,1+2+3+...+250>3e4,也就是说步长最多有250种,即第二维有效的只有500个,所以可以在这个地方对空间经行优化,第二维表示上一步跳了j+d-250步,因此第二维只需要存j即可,还有一个问题是边界一定要处理好,下一步的位置一定要比当前的位置大,因为步长一定是正数

AC代码:

#include "iostream"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define ll long long
#define endl ("
")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ft (frist)
#define sd (second)
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const long long INF = 1e18+1LL;
const int inf = 1e9+1e8;
const int N=3e4+10;
const ll mod=1e9+7;

int dp[N+100][600],v[N+100],n,d;
int main(){
    cin>>n>>d;
    for(int i=1; i<=n; ++i){
        int x; cin>>x;
        v[x]++;
    }
    mem(dp,-1); dp[d][250]=v[d];
    for(int i=d; i<=N; ++i){
        for(int j=0; j<=500; ++j){
            int nex=i+d+j-250;
            if(dp[i][j]==-1) continue;
            if(nex>i && nex<N) dp[nex][j]=max(dp[nex][j],dp[i][j]+v[nex]);
            if(nex-1>i && nex-1<N) dp[nex-1][j-1]=max(dp[nex-1][j-1],dp[i][j]+v[nex-1]);
            if(nex+1>i && nex-1<N) dp[nex+1][j+1]=max(dp[nex+1][j+1],dp[i][j]+v[nex+1]);
        }
    }
    int ans=0;
    for(int i=0; i<=N; ++i){
        for(int j=0; j<=500; ++j){
            ans=max(ans,dp[i][j]);
        }
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/max88888888/p/7294507.html