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;
    }
    
  • 相关阅读:
    事务隔离级别
    OpenSessionInView
    图像平滑处理(滤波)
    [原]Nginx+Lua服务端合并静态文件
    检查数据倾斜分布
    SQL Server研究之统计信息—发现过期统计信息并处理具体解释
    GDALWarp设置GDALWarpOptions::dfWarpMemoryLimit过大时处理失败
    Android Studio 2.0 稳定版新特性介绍
    供应商和管理员查看供应商地址簿信息SQL
    Table AdvanceTable针对表内行禁用multipleSelection , singleSelection
  • 原文地址:https://www.cnblogs.com/DianeSoHungry/p/11406212.html
Copyright © 2011-2022 走看看