以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;
}

转载于:https://www.cnblogs.com/DianeSoHungry/p/11406212.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C#跳跃游戏的源代码: using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { public float jumpForce = 10f; public float moveSpeed = 5f; public Transform groundCheck; public LayerMask groundLayer; public GameObject gameOverPanel; private Rigidbody2D rb; private Animator anim; private bool isJumping = false; private bool isGrounded = false; void Start() { rb = GetComponent<Rigidbody2D>(); anim = GetComponent<Animator>(); } void Update() { if (Input.GetKeyDown(KeyCode.Space) && isGrounded) { isJumping = true; rb.velocity = Vector2.up * jumpForce; } anim.SetBool("isJumping", isJumping); anim.SetFloat("yVelocity", rb.velocity.y); float horizontalInput = Input.GetAxisRaw("Horizontal"); rb.velocity = new Vector2(horizontalInput * moveSpeed, rb.velocity.y); if (rb.velocity.x > 0) { transform.localScale = new Vector3(1, 1, 1); } else if (rb.velocity.x < 0) { transform.localScale = new Vector3(-1, 1, 1); } isGrounded = Physics2D.OverlapCircle(groundCheck.position, 0.1f, groundLayer); if (!isGrounded) { gameOverPanel.SetActive(true); Time.timeScale = 0f; } } private void OnTriggerEnter2D(Collider2D collision) { if (collision.CompareTag("Coin")) { Destroy(collision.gameObject); } } } 在此代码中,我们定义了玩家控制器的变量和属性。我们还定义了开始和更新函数,以便在游戏中实现跳跃和移动。我们还在代码中添加了碰撞检测和游戏结束的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值