动态规划 -- 机器人步数

问题描述

假设有排成一行的N个位置,记为1-N,N一定大于或者等于2,开始时机器人在其中的M位置上(M一定是1-N中的一个);

如果机器人来到1位置,那么下一步只能往右到2位置;

如果在N位置,下一步只能到N-1位置;

如果在中间位置,下一步可以往左或右;

规定机器人必须走K步,最终来到P位置(P在1-N之间);

给定四个参数N、M、K、P,返回方法数。

解决思路

首先考虑递归实现,暴力递归,设当前的位置为 cur,剩余步数为 rest,那不函数初始调用的参数就分别为:M、K。
考虑递归的优化,如果某次来到的cur和rest,之前已出现过,则可以利用之前的结果,因此考虑将中间结果缓存起来,即记忆式搜索。
继续优化,发现二维数组的某个值可以完全由其邻居推断出来,即完全动态规划。
三种方案的代码实现如下:

class RobotWalk:
    """
    机器人走路步数
    """
    def solution1(self, N, start, aim, K):
        """

        :param N: N个位置,记为1-N,N一定大于或者等于2
        :param start: 开始时机器人在其中的start位置上
        :param aim: 最终来到的位置
        :param K: 总过需要走K步
        :return: 多少种走法
        """
        if N < 2 or start < 1 or start > N or aim < 1 or aim > N or K < 1:
            return -1
        return self.process1(start, K, aim, N)

    def process1(self, cur, rest, aim, N):
        """

        :param cur: 机器人当前来到的位置是cur
        :param rest: 机器人还有rest步需要去走
        :param aim: 最终的目标是aim
        :param N:
        :return:
        """
        if rest == 0:
            return 1 if cur == aim else 0
        if cur == 1:
            return self.process1(2, rest-1, aim, N)
        if cur == N:
            return self.process1(N-1, rest-1, aim, N)

        return self.process1(cur-1, rest-1, aim, N) + self.process1(cur+1, rest-1, aim, N)

    def solution2(self, N, start, aim, K):
        """
        递归 --> 记忆式搜索【弱动态规划】
        :param N:
        :param start:
        :param aim:
        :param K:
        :return:
        """
        if N < 2 or start < 1 or start > N or aim < 1 or aim > N or K < 1:
            return -1
        dp = [[-1]*(K+1) for _ in range(N+2)]
        return self.process2(start, K, aim, N, dp)

    def process2(self, cur, rest, aim, N, dp):
        """

        :param cur:
        :param rest:
        :param aim:
        :param N:
        :param dp: 空间换时间,减少重复计算
        :return:
        """
        if dp[cur][rest] != -1:
            return dp[cur][rest]
        # 之前没算过!
        if rest == 0:
            ans = 1 if cur == aim else 0
        elif cur == 1:
            ans = self.process2(2, rest - 1, aim, N, dp)
        elif cur == N:
            ans = self.process2(N - 1, rest - 1, aim, N, dp)
        else:
            ans = self.process2(cur-1, rest-1, aim, N, dp) + self.process2(cur+1, rest-1, aim, N, dp)

        # 更新数组
        dp[cur][rest] = ans
        return ans

    def solution3(self, N, start, aim, K):
        """
        记忆式搜索【弱动态规划】--> 强动态规划
        :param N:
        :param start:
        :param aim:
        :param K:
        :return:
        """
        if N < 2 or start < 1 or start > N or aim < 1 or aim > N or K < 1:
            return -1
        dp = [[0] * (K + 1) for _ in range(N + 1)]
        dp[aim][0] = 1
        for rest in range(1, K+1):
            dp[1][rest] = dp[2][rest-1]
            for cur in range(2, N):
                dp[cur][rest] = dp[cur-1][rest-1] + dp[cur+1][rest-1]
            dp[N][rest] = dp[N-1][rest-1]

        return dp[start][K]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP_wendi

谢谢您的支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值