package day_16;
/**
* 暴力递归到动态规划02:
* 假设有排成一行的N个位置,记为1~N,N 一定大于或等于 2
* 开始时机器人在其中的M位置上(M 一定是 1~N 中的一个)
* 如果机器人来到1位置,那么下一步只能往右来到2位置;
* 如果机器人来到N位置,那么下一步只能往左来到 N-1 位置;
* 如果机器人来到中间位置,那么下一步可以往左走或者往右走;
* 规定机器人必须走 K 步,最终能来到P位置(P也是1~N中的一个)的方法有多少种
* 给定四个参数 N、M、K、P,返回方法数。
* @Author huawei
* @Date 2021/5/12 15:26
* @Version 1.0
*/
public class Code01_RobotWalk {
/**
* 首先使用暴力递归
* @param N 一共N个位置
* @param M 此时机器人在的位置
* @param K 规定机器人走的步数
* @param P 机器人想要来到的目的位置
* @return
*/
public static int getAllMethod(int N,int M,int K,int P){
if(N < 1 || K < 0 || P > N || M < 0 || P < 0 || M > N ){
return -1;
}
return process(M,K,N,P);
}
/**
* 递归函数的意思:此时机器人的位置为M,剩余步数还剩K,目标位置P,机器人在这个时候来到目标P的方法有多少种
* @param M 此时机器人来到的位置
* @param K 剩余步数
* @param N 有多少个位置
* @param P 目标位置
* @return
*/
public static int process(int M,int K,int N,int P){
// base case
if( K == 0 ){
// 判断当前位置是否等于目标位置,如果相等就 + 1
return M == P ? 1 : 0;
}else{
// 如果不想等,有三种情况,如果走到了最左,则只有往右边走
if(M == 1){
return process(2,K-1,N,P);
}else if( M == N){
// 如果走到了最右,只有往左边走
return process(M-1,K-1,N,P);
}else{
// 如果都不是,那么就是在中间,那么即可以往左边走也可以往右边走,就是两者的总和
return process(M-1,K-1,N,P) + process(M+1,K-1,N,P);
}
}
}
public static int getAllMethod01(int cur,int aim,int N,int step){
// 创建缓存表
int [][] dp = new int[N + 1][step + 1];
for(int i = 0 ; i <= N ; i++){
for(int j = 0 ; j <= step ; j++){
dp[i][j] = -1;
}
}
return process1(cur,aim,N,step,dp);
}
/**
* 利用傻缓存法来改进这个暴力递归
* 所谓的动态规划其实就是找出暴力递归中计算相同的递归数,将每一次递归得到的值放入到一个缓存当中去,然后
* 如果有相同的递归命中了缓存,直接去缓存中取即可
* 缓存表的确定,在于可变长参数的范围,此题可变长参数的返回就是cur 1 - N step 0 - N
* 所以就可以确认缓存表的变化啦
* @param cur
* @param aim
* @param N
* @param step
* @return
*/
public static int process1(int cur,int aim,int N,int step,int [][] dp){
// base case
if(step == 0){
return cur == aim ? 1 : 0;
}
if(dp[cur][step] != -1){
return dp[cur][step];
}else{
int ans = 0;
if(cur == 1){
ans = process1(2,aim,N,step - 1,dp);
}else if(cur == N){
ans = process1(N-1,aim,N,step-1,dp);
}else{
ans = process1(cur - 1, aim , N , step - 1,dp) + process1(cur + 1, aim , N ,step - 1,dp);
}
dp[cur][step] = ans;
return ans;
}
}
/**
* 利用动态规划,使用状态转移来代替暴力递归
* 犯法:找出对应的状态依赖
* @param cur
* @param aim
* @param N
* @param step
* @return
*/
public static int getAllMethod02(int cur,int aim,int N,int step){
int [][] dp = new int[N + 1][step + 1];
dp[aim][0] = 1;
for(int i = 1 ; i <= step ; i++){
dp[1][i] = dp[2][i-1];
for(int j = 2 ; j < N ; j++){
dp[j][i] = dp[j + 1][i - 1] + dp[j - 1][i - 1];
}
dp[N][i] = dp[N - 1][i - 1];
}
return dp[cur][step];
}
public static void main(String[] args) {
System.out.println(getAllMethod(3, 1, 2, 3));
System.out.println(getAllMethod01(1, 3, 3, 2));
System.out.println(getAllMethod01(5, 7, 7, 4));
System.out.println(getAllMethod02(5, 7, 7, 4));
}
}
数据结构和算法从暴力到动态规划02-机器人找路问题
最新推荐文章于 2026-06-23 15:50:44 发布
本文探讨了一个经典的机器人行走问题,即在一个固定长度的路径上,机器人从指定起点出发,在限定步数内到达目标点的方法数量。文章提供了三种解决方案:暴力递归、使用缓存改进的递归及动态规划。

1633

被折叠的 条评论
为什么被折叠?



