当青训营遇上码上掘金

36 阅读2分钟

当青训营遇上码上掘金

寻友之旅

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

动态规划解法:

  1. 小青在小码前面———— 步行回退 return N-K

  2. 小青就在小码位置—— return 0

  3. 小青在小码后面——动态规划

    • 状态定义

      int* dp = new int[100000] {}; //dp[i]:从N到i需要花费最短时间
      复制代码
      
    • 初始状态

      dp[N] = 0; // 从N到N需要花费0分钟
      res = INT_MAX; // 最短时间初始化为INT_MAX
      复制代码
      
    • 结果:最短时间

      /*
          res = min(从N到K的最短时间,从N到K+j再回退j的最短时间)
              = min (dp[K], dp[k+j]+j);
      */
      复制代码
      
    • 状态转移

      /*
          0=<i<N——dp[i] = dp[i+1]+1; 步行回退   
          i>N————dp[i] = min(步行到i,总公交到i)+1  
                       = min(dp[i-1], dp[i/2])+1;                       i-1>=0且i/2为偶数
                       = min(dp[i-1], dp[(i-1)/2]+1, dp[(i+1)/2]+1)+1;  i-1>=0且i/2为奇数
      */
      for (int i = N - 1; i >= 0; i--) {
          dp[i] = dp[i + 1] + 1;
      }
      for (int i = N + 1; i <= 100000; i++) {
          int walk = dp[i - 1] + 1;
          int bus = dp[i / 2] + 1;
          if (i % 2 != 0) { bus = min(dp[(i + 1) / 2], dp[(i - 1) / 2]) + 2; }
          dp[i] = min(walk, bus);
          
          if (i >= K) {
              res = min(res, dp[i] + i - K);
          }
      }
      

动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果。