来自左程云老师书中的一道题
【题目】
假设有排成一行的 N 个位置,记为 1~N,N 一定大于或等于 2。开始时机器人在其中的 M
位置上(M 一定是 1~N 中的一个),机器人可以往左走或者往右走,如果机器人来到 1 位置,
那么下一步只能往右来到 2 位置;如果机器人来到 N 位置,那么下一步只能往左来到 N-1 位置。
规定机器人必须走 K 步,最终能来到 P 位置(P 也一定是 1~N 中的一个)的方法有多少种。给
定四个参数 N、M、K、P,返回方法数。
【举例】
N=5,M=2,K=3,P=3
上面的参数代表所有位置为 1 2 3 4 5。机器人最开始在 2 位置上,必须经过 3 步,最后到
达 3 位置。走的方法只有如下 3 种:
1)从 2 到 1,从 1 到 2,从 2 到 3
2)从 2 到 3,从 3 到 2,从 2 到 3
3)从 2 到 3,从 3 到 4,从 4 到 3
所以返回方法数 3。
N=3,M=1,K=3,P=3
上面的参数代表所有位置为 1 2 3。机器人最开始在 1 位置上,必须经过 3 步,最后到达 3
位置。怎么走也不可能,所以返回方法数 0。
递归代码:
public static int process(int N,int M,int K, int P) {
if(K == 0) {
return M == P? 1:0;
}
if(M ==1) {
return process(N,M+1,K-1,P);
}
if(M == N) {
return process(N,M-1,K-1,P);
}
return process(N,M+1,K-1,P) + process(N,M-1,K-1,P);
}
递归推导动态规划
前提:判断是否是无后效性的。所谓无后效性是指是指一个递归状态的返回值与怎么到达这个状态的路径无关。
动态规划代码:
public static int process2(int N,int M,int K, int P) {
int[][] dp = new int[K+1][N+1];
dp[0][P] = 1;
for(int i =1;i<=K;i++) {
for(int j=1;j<=N;j++) {
if(j==1) {
dp[i][j] = dp[i-1][j+1];
} else if(j == N) {
dp[i][j] = dp[i-1][j-1];
} else {
dp[i][j] = dp[i-1][j+1] + dp[i-1][j-1];
}
}
}
return dp[K][M];
}