zoukankan      html  css  js  c++  java
  • codeforces505C_记忆化搜索

    题目链接http://codeforces.com/problemset/problem/505/C

    题目大意:

    现在有30000个岛,最开始站在第0个岛上,第一次向右跳d个岛。

    若上一次为d,这次只能向右跳d-1,d,和d+1步。跳的步数步数不能为0,当不能向右跳时即停止。

    思路:

    不考虑时间和空间,最朴素的方法就是设dp[i][j]表示上一步跳了j步,当前在i点上,之后的转移也很好写

    然而这明显是会爆时间爆空间的,不过我们可以发现,二维的j并不需要等于30000,而只会在[d-245,d+245]这个范围内!

    最糟糕的情况,d为1,跳到第30000个岛要跳的次数为n, 有等式(1 + n) * n / 2 = 30000, 解出n大约等于250;[-250, 250], 所以dp[30010][500]就够了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int N = 250;
     8 int n, d, a;
     9 int dp[30010][510], val[30010];//val[i]表示第i个岛有多少宝石
    10 int find(int p, int f)//p为到达的岛
    11 {
    12     if(dp[p][N + f] != -1)//记忆化搜索关键
    13         return dp[p][N + f];
    14     int temp = 0;
    15     for(int i = -1; i <= 1; i++)
    16     {
    17         if(d + f + i < 1 || p + d + f + i > 30000)//最初的步长d + (f + i)加减1后的总步数,如果小于1,说明跳的步数为0,不符合题意
    18             continue;//为当前岛的编号p + (d + f + i)这次跳的步数,大于30000就不符合题意啦
    19         temp = max(temp, find(p + d + f + i, f + i));
    20         return dp[p][N + f] = temp + val[p];
    21 }
    22 int main()
    23 {
    24     scanf("%d %d", &n, &d);
    25     memset(val, 0, sizeof(val));
    26     for(int i = 1; i <= n; i++){
    27         scanf("%d", &a);
    28         val[a]++;
    29     }
    30     memset(dp, -1, sizeof(dp));
    31     printf("%d
    ", find(d, 0));
    32     return 0;
    33 }
  • 相关阅读:
    AdaBoost算法学习
    梯度下降与随机梯度下降
    Logistic Regression学习
    PCA算法
    VS2013常见错误排查
    K临近算法
    遗传算法小结
    SLIC超像素(superpixel)算法
    openslide api函数概要
    线程钩子
  • 原文地址:https://www.cnblogs.com/luomi/p/5540458.html
Copyright © 2011-2022 走看看