假设有排成一行的N个位置,记为1~N,N一定大于或等于2
开始时,机器人在其中的M位置上(M一定是1~N中的一个)
如果机器人来到1位置,那么下一步只能往右来到2位置
如果机器人来到N位置,那么下一步只能往左来到N-1位置
如果机器人来到中间位置,那么下一步可以往左也可以往右
规定机器人必须走K步,最终能来到P位置的方法有多少种?
给定4个参数N,M,K,P,返回方法数。
暴力方法
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
public class RobotWalk{
public static int ways1(int N,int M,int K,int P){
//参数无效直接返回0
if(N < 2 || K < 1 || M < 1 || M > N || P < 1 || P < N){
return 0;
}
//总共N个位置,从M点出发,还剩下K步,返回最终能到达P的方法数
return walk(N,M,K,P);
}
//N 位置为1-N,固定参数
//cur 当前在cur位置,可变参数
//rest,还剩下res步没有走,可变参数
//p,最终目标是P,固定参数
public static int walk(int N,int cur,int rest,int P){
if(rest == 0){
return cur == P ? 1 : 0;
}
if(cur == 1){
return walk(N, 2, rest - 1, P);
}
if(cur == N){
return walk(N, N - 1, rest - 1, P);
}
return walk(N, cur + 1, rest - 1, P) + walk(N, cur - 1, rest - 1, P);
}
}
但是暴力递归会重复搜索,增加一个缓存机制,把每次搜索的数据记录下来,这样就成为了动态规划。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
public class RobotWalk{
public static int waysCache(int N,int M,int K,int P){
//参数无效直接返回0
if(N < 2 || K < 1 || M < 1 || M > N || P < 1 || P < N){
return 0;
}
//总共N个位置,从M点出发,还剩下K步,返回最终能到达P的方法数
int[][] dp = new int[N + 1][ K + 1];
for(int row = 0; row <= N; row++){//行
for(int col = 0; col <= K; col++){
dp[row][col] = -1;
}
}
return walkCache(N,M,K,P,dp);
}
//N 位置为1-N,固定参数
//cur 当前在cur位置,可变参数
//rest,还剩下res步没有走,可变参数
//p,最终目标是P,固定参数
public static int walkCache(int N,int cur,int rest,int P,int[][] dp){
if(dp[cur][rest] != -1){
return dp[cur][rest];
}
if(rest == 0){
dp[cur][rest] = cur == P ? 1 : 0;
return dp[cur][rest];
}
if(cur == 1){
dp[cur][rest] = walkCache(N, 2, rest - 1, P,dp);
return dp[cur][rest];
}
if(cur == N){
dp[cur][rest] = walkCache(N, N - 1, rest - 1, P, dp);
return walkCache(N, N - 1, rest - 1, P,dp);
}
dp[cur][rest] = walkCache(N, cur + 1, rest - 1, P,dp) + walkCache(N, cur - 1, rest - 1, P,dp);
return dp[cur][rest];
}
}