动态规划-机器人走路

题目描述

假设有排成一行的N个位置,记为1~N,(N>=2),开始时机器人在start位置,有如下约束

  • 机器人在1位置,下一步只能走到2位置
  • 机器人在N位置,下一步只能走到N-1位置
  • 机器人在其他位置,下一步能走左边,也能走右边
    求机器人从start位置经过k步到达target位置的方法数。

思路

base-case是当机器人没有步数可走时,若current位置等于target位置,则方法数+1,在加上题目给定的边界的限制条件。
优化思路:可以看出决定函数返回值的是current,rest,可以建立二维表来存储返回值,在第二次遇到时直接取值
而题目所要求得可以直接根据表来得到,依据初始化条件和函数间的依赖可以直接得到结果。可以看出在填表的过程中和原题意基本没有关系,只是根据递归函数来填表。

求解

#include <iostream>

using namespace std;
//现在在current位置,还有rest步要走,到target的方法数
int process1(int N, int current, int rest, int target);
int processdp(int N, int current, int rest, int target, int **dp);
int processdp2(int N, int current, int rest, int target);
int main() {
    cout << process1(6,3,5,6) << endl;
    int N = 6, K = 5;
    int dp[N+1][K+1];
    for(int i = 1; i <= N; i++) {
        for(int j = 1; j <= K; j++) {
            dp[i][j] = -1;
        }
    }
    cout << processdp(6,3,5,6,(int**)dp) << endl;
    cout << processdp2(6,3,5,6) << endl;
    return 0;
}
//暴力递归
int process1(int N, int current, int rest, int target) {
    if(rest == 0) {//已经没有步数要走
        return (current == target) ? 1 : 0;//?:表达式
    } else if(current == 1) {//1->2位置
        return process1(N, 2, rest - 1, target);
    } else if(current == N) {//N->N-1位置
        return process1(N, N-1, rest - 1, target);
    } else {//中间位置
        return process1(N, current-1, rest - 1, target) + process1(N, current+1, rest-1, target);
    }
}
//缓存方法
int processdp(int N, int current, int rest, int target, int **dp) {
    int res;
    if(dp[current][rest] != -1) { //不等于-1,已经算过,直接返回
        return dp[current][rest];
    }
    if(rest == 0) {//已经没有步数要走
        res = (current == target) ? 1 : 0;//?:表达式
    } else if(current == 1) {
        res = process1(N, 2, rest - 1, target);
    } else if(current == N) {
        res = process1(N, N-1, rest - 1, target);
    } else {
        res = process1(N, current-1, rest - 1, target) + process1(N, current+1, rest-1, target);
    }
    dp[current][rest] = res;
    return res;
}
//填表
int processdp2(int N, int current, int rest, int target) {
    int dp[N+1][rest+1];
    for(int i = 0; i <= N; i++) {
        for(int j = 0; j <=rest; j++) {
            dp[i][j] = 0;
        }
    }
    dp[target][0] = 1;
    for(int j = 1; j <= rest; j++) {
        dp[1][j] = dp[2][j-1];
        for(int i = 2; i < N; i++) {
            dp[i][j] = dp[i-1][j-1] + dp[i+1][j-1];
        }
        dp[N][j] = dp[N-1][j];
    }
    return dp[current][rest];
}
posted @   sakuzeng  阅读(100)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示