zoukankan      html  css  js  c++  java
  • 以Jump Game为例,逐层击破动态规划

    本文以LeetCode上Jump Game为案例,分别用递归法、递归+动态规划、动态规划完成解答。
    (本文由DianeSoHungry原创,转载请说明出处!https://www.cnblogs.com/DianeSoHungry/p/11406212.html)
    语言:C++

    题目

    Given an array of non-negative integers, you are initially positioned at the first index of the array.
    Each element in the array represents your maximum jump length at that position.
    Determine if you are able to reach the last index.

    Example 1:

    Input: [2,3,1,1,4]
    Output: true
    Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
    

    Example 2:

    Input: [3,2,1,0,4]
    Output: false
    Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index.
    

    递归法

    思路是这样的:

    若你被放在下标为i的位置,判断你能到达终点的依据是“从当前位置往后到i+nums[i]位置,是否至少存在一个位置,从这个位置你能到达终点。

    //////recursive backtracking////////
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    bool canJump(int* nums, int n){
        if (n==1) {
            return true;
        }
        if (nums[0]==0) {
            return false;
        }
        bool res = false;
        for (int i = 1; i <= nums[0]; i++) {
            res = res || canJump(&nums[i], n-i);
        }
        return res;
    }
    
    int main(){
        int n;
        cin >> n;
        int nums[n];
        for (int i = 0; i < n; i++) {
            int num;
            scanf("%d", &num);
            nums[i] = num;
        }
        cout << canJump(nums, n);
        return 0;
    }
    

    递归 + 动态规划 (Top-down)

    单纯递归造成的问题是:重复。例如:nums=[5, 3, 4, 2]。位置2的返回既要被位置0调用,还要被位置1调用。加上memo记忆表使得当

    ////////recursion +  memoization table////////
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    bool canJump (int* nums, int* memo, int n) {
        if (memo[0] != -1) {
            return memo[0];
        }
        if (n == 1) {
            memo[0] = 1;
            return true;
        }
        if (nums[0]==0) {
            memo[0] = 0;
            return false;
        }
        bool res = false;
        for (int i = 1; i <= nums[0]; i++) {
            res = res || canJump(&nums[i], &memo[i], n-i);
        }
        memo[0] = res;
        return res;
    }
    
    int main(){
        int n;
        cin >> n;
        int nums[n];
        int memo[n];
        for (int i = 0; i < n; i++) {
            int num;
            scanf("%d", &num);
            nums[i] = num;
            memo[i] = -1;
        }
        cout << canJump(nums, memo, n);
        return 0;
    }
    

    动态规划(Bottom-up)

    该方法超时,下文利用原数组作为记忆表解决了超时问题。

    ////////Bottom-up Dynamic Programming////////
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    bool canJump(vector<int> &nums) {
        vector<bool> memo;
        for (int i = 0; i < nums.size(); i ++) {
            memo.push_back(false);
        }
        memo.back() = true;
        for (int i = nums.size() - 2; i > -1; i--) {
            for (int j = 1; j <= nums[i] && i+j < nums.size(); j++) {
                memo[i] = memo[i] || memo[i+j];
                if (memo[i] == true) {
                    break;
                }
            }
        }
        return memo[0];
        
    }
    
    int main(){
        int n;
        cin >> n;
        vector<int> nums;
        for (int i = 0; i < n; i++) {
            int num;
            scanf("%d", &num);
            nums.push_back(num);
        }
        cout << canJump(nums);
        return 0;
    }
    

    动态规划(Bottom-up & Inplace)

    ////////Bottom-up Dynamic Programming////////
    #include<iostream>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    bool canJump(vector<int> &nums){
        nums.back() = 1;
        for (int i = nums.size() - 2; i > -1; i--) {
            int tmp = 0;
            for (int j = 1; j <= nums[i] && i+j < nums.size(); j++) {
                tmp = tmp || nums[i+j];
                if (tmp) {
                    break;
                }
            }
            nums[i] = tmp;
            for (auto k:nums) {
                cout << k;
            }
            cout << endl;
        }
        return nums[0];
    }
    
    int main(){
        int n;
        cin >> n;
        vector<int> nums;
        for (int i = 0; i < n; i++) {
            int num;
            scanf("%d", &num);
            nums.push_back(num);
        }
        cout << canJump(nums);
        return 0;
    }
    
  • 相关阅读:
    binder机制理解
    Android 资源目录
    Andriod 构建项目流程
    dpi、ppi 、dp、sp、px、 pt相关概念
    短语、直接短语和句柄
    MySql优化
    java虚拟机内存管理
    redis
    linux——nginx的安装及配置
    linux——高级文本处理命令之wc、cut、sort
  • 原文地址:https://www.cnblogs.com/DianeSoHungry/p/11406212.html
Copyright © 2011-2022 走看看