机器人到达指定位置的方法数问题

机器人到达指定位置的方法数问题

作者:Grey

原文地址:

博客园:机器人到达指定位置的方法数问题

CSDN:机器人到达指定位置的方法数问题

题目描述

链接:https://www.nowcoder.com/questionTerminal/54679e44604f44d48d1bcadb1fe6eb61
来源:牛客网

假设有排成一行的N个位置,记为1~N,开始时机器人在M位置,机器人可以往左或者往右走,如果机器人在1位置,那么下一步机器人只能走到2位置,如果机器人在N位置,那么下一步机器人只能走到N-1位置。规定机器人只能走k步,最终能来到P位置的方法有多少种。由于方案数可能比较大,所以答案需要对1e9+7取模。

暴力解

定义递归函数

long ways(int len, int start, int step, int end)

递归含义表示: 机器人从坐标 start 开始,只能走 step 步,到达 end 的方法数是多少

接下来是 base case,

if (step == 0) {
    if (start == end) {
        return 1L;
    }
    return 0L;
}

如果 step 只剩下 0 步,说明没有步数可以走了,此时,如果 start == end ,表示正好就在目的地,返回一种方法数;

否则,返回 0 种方法数。

接下来是普遍情况,如果 start == 0,只能向右边走,即: ways(len, start + 1, step - 1, end)

如果 start == len - 1,只能向左边走,即: ways(len, start - 1, step - 1, end)

不在两端位置,则既可以向左边走,也可以向右边走,即: (ways(len, start - 1, step - 1, end) + ways(len, start + 1, step - 1, end))

暴力解法完整代码如下

    public static long ways(int len, int start, int step, int end) {
        if (step == 0) {
            if (start == end) {
                return 1L;
            }
            return 0L;
        }
        // step不止一步
        if (start == 0) {
            return ways(len, start + 1, step - 1, end);
        } else if (start == len - 1) {
            return ways(len, start - 1, step - 1, end);
        } else {
            return (ways(len, start - 1, step - 1, end) + ways(len, start + 1, step - 1, end));
        }
    }

超时

机器人到达指定位置的方法数问题

动态规划-缓存法(可 AC)

上述暴力递归过程,可变参数有两个 start,step;可以设置一个二维数组 dp,用于缓存递归中间过程的解,

long[][] dp = new long[len][step + 1];

dp[i][j]表示 ways(len,i,j,end)的值, dp数组的值均初始化为 -1。

上述暴力递归过程增加这个 dp 参数,如果 dp[i][j] != -1,则说明已经算过这个递归过程,直接返回 dp[i][j]的值即可。

完整代码如下

    public static long ways(int len, int start, int step, int end) {
        long[][] dp = new long[len][step + 1];
        for (int i = 0; i < len; i++) {
            for (int j = 0; j

动态规划解-严格位置依赖(可 AC)

回到暴力递归解,伪代码如下

    public static long ways(int len, int start, int step, int end) {
        ......

        if (start == 0) {
            return ways(len, start + 1, step - 1, end);
        } else if (start == len - 1) {
            return ways(len, start - 1, step - 1, end);
        } else {
            return (ways(len, start - 1, step - 1, end) + ways(len, start + 1, step - 1, end));
        }
    }

根据缓存法得知,该递归过程使用一个二维数组 dp 即可存下所有结果,其中

dp[i][j]表示 ways(len,i,j,end)的值,

通过观察上述暴力递归过程, dp[i][j]依赖的位置是 dp[i+1][j-1]dp[i-1][j-1]

所以,依据上述递归过程,可以改成严格位置的动态规划版本,完整代码如下

    public static long ways(int len, int start, int step, int end) {
        long[][] dp = new long[len][step + 1];
        // 填好第0列
        dp[end][0] = 1L;
        for (int j = 1; j < step + 1; j++) {
            for (int i = 0; i < len; i++) {
                if (i == 0) {
                    dp[i][j] = dp[1][j - 1];
                } else if (i == len - 1) {
                    dp[i][j] = dp[len - 2][j - 1];
                } else {
                    dp[i][j] = dp[i - 1][j - 1] % MOD + dp[i + 1][j - 1] % MOD;
                }
            }
        }
        return dp[start][step];
    }

动态规划解-空间压缩版(可 AC)

通过上述严格位置的动态规划版本可以得知, dp[i][j]位置,依赖的位置是 dp[i+1][j-1]dp[i-1][j-1],

示例图如下

机器人到达指定位置的方法数问题

而且,通过上述动态规划解,可以得知第 0 列中,除了 dp[end][0] = 1L,其余都是 0,所以 dp 的第0列可以直接填充

机器人到达指定位置的方法数问题

所以,只需要用 一个一维数组表示第 0 列,然后根据依赖关系,通过第 0 列推出第一列的值,一维数组此时表示第一列的值,依次这样递推下去,一直到最后一列,得解,这种方法就可以将二维数组压缩成一维数组,节省了空间复杂度。

完整代码如下

    public static long ways(int len, int start, int step, int end) {
        long[] dp = new long[len];
        dp[end] = 1L;
        long tmp = 0;
        for (int j = 1; j < step + 1; j++) {
            for (int i = 0; i < len; i++) {
                long ways = dp[i];
                if (i == 0) {
                    dp[i] = dp[1] % MOD;
                } else if (i == len - 1) {
                    dp[i] = tmp % MOD;
                } else {
                    dp[i] = tmp % MOD + dp[i + 1] % MOD;
                }
                tmp = ways;
            }
        }
        return dp[start];
    }

更多

算法和数据结构笔记

Original: https://www.cnblogs.com/greyzeng/p/16837512.html
Author: Grey Zeng
Title: 机器人到达指定位置的方法数问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/799921/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • HC32L110(五) Ubuntu20.04 VSCode的Debug环境配置

    本文介绍在Ubuntu20.04下, VSCode中如何设置对 HC32L110 进行 debug 如果转载, 请注明出处. 本文使用的软硬件环境已经在前面介绍 基于 HC32L1…

    Python 2023年10月23日
    054
  • 读写权限详解

    本篇博客主要通过三个问题来理清C/C++中的读写权限问题: const变量可以赋值给非const引用吗? const变量的地址可以赋值给非const指针吗? const普通变量可以…

    Python 2023年11月6日
    046
  • Python绘图库:Matplotlib入门教程

    在后台回复【阅读书籍】 即可获取python相关电子书~ Hi,我是山月。 在,我们提到过 Matplotlib。 它是一个非常强大的绘图库,能很轻松地将数据图形化,并且提供多样化…

    Python 2023年9月2日
    045
  • 嵌入层(embedding)(自然语言处理)

    作用1:降维:因为使用独热编码虽然计算简单,但是占用太多不必要的资源,所以使用嵌入层(embedding)进行降维,和1*1卷积有异曲同工之妙。 因为有时候图片降维后的特征只能笼统…

    Python 2023年10月29日
    038
  • python之numpy库的应用

    numpy是由c语言编写的,运行速度比python 循环快很多 在数据处理的过程中,遇到使用 python for循环实现一些向量化,矩阵化操作的时候,要优先考虑用numpy 1 …

    Python 2023年8月27日
    082
  • Python中的路径

    windows路径使用的是\,linux路径使用的是/。 特别的,在windows系统中如果有这样的一个路径 D:\nxxx\txxx\x1,程序会报错。因为在路径中存在特殊符 \…

    Python 2023年6月3日
    074
  • 数据科学-pandas的分组和聚合

    目录 导入 分组和聚合 索引和复合索引 总结 导入 现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国的星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量的情…

    Python 2023年8月7日
    047
  • for循环中 i++ 和 ++i 区别

    一、for循环中 i++的使用 for (int i = 0;i < 10;i++){ 二、for循环中 ++i 的使用 for (int i = 0;i Original:…

    Python 2023年11月9日
    031
  • python模块之 celery定时任务

    文章目录 一、celery的安装、使用 * 1.celery的安装、配置 2.celery的使用 一、celery的安装、使用 1.celery的安装、配置 对于django的版本…

    Python 2023年8月6日
    096
  • 了解模型开发与部署,看这里!

    11月24日下午15:00顶象第十期业务安全系列大讲堂系列课程《Xintell 模型平台 》正式开讲。 顶象人工智能专家&研发总监无常从模型平台的现状与需求出发,带大家了解…

    Python 2023年10月7日
    046
  • Python基础学习之“数组的存储和处理”

    基于NUMPy模块的数组存储和处理一:创建数组 ❝NumPy模块可以构建多维数据的容器,将各种的数据快速的整合在一块,完成多维数据的计算及大型矩阵的存储和处理。❞ 使用 array…

    Python 2023年8月29日
    051
  • Pandas数据分析教程(2)-数据读取之普通索引、loc/iloc索引

    在上一期中,我们简单介绍了 Series和 DataFrame两种Pandas中常用的数据结构,那么问题来了,假设我已经有了这两种数据,如何从中提取我想要的部分? DataFram…

    Python 2023年8月16日
    059
  • Python-Scrapy安装

    描述:安装爬虫框架Scrapy、基本使用、知识点总结。 目录 🏆一、Scrapy安装 ⭐️1.1、scrapy是什么 ⭐️1.2、安装环境 ⭐️1.3、步骤安装 ⭐️1.4、测试是…

    Python 2023年10月1日
    044
  • Python numpy.abs和abs函数别再傻傻分不清了

    不知道小伙伴们在写代码的时候有没有区分开numpy.abs和abs函数,别小看这两个函数,如果在写程序的时候正确区分使用这两个函数可以使自己的程序运行效率大大提升。 别看这两个函数…

    Python 2023年8月23日
    062
  • 零钱兑换问题

    零钱兑换问题 作者:Grey 原文地址: 博客园:零钱兑换问题 CSDN:零钱兑换问题 题目描述 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,…

    Python 2023年10月19日
    042
  • Python-Falsk获取表单数据(前端数据)

    本文将给大家讲解一下Falsk写的一个表单数据获取——获取数据准备工作: python3.7.3 falsk2.0.1(最新版) 一、request方法 R…

    Python 2023年8月10日
    053
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球