第一个参数int N,有N个位置1,2,3,4~N,N>1
第二个参数int S,开始位置,有个机器人停在哪个位置上,是1~N中间的。
第三个参数int E,是目标位置,从S出发到E
第四个参数int K,机器人必须走K步,要想从S到达E,有多少种方法?可以随意向左向右走
public static int ways1(int N, int start, int aim, int K) {if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) {return -1;}return process1(N,aim,start,K );}// 有哪些位置?1~N 固定参数// 最终的目标是aim, 固定参数// 机器人当前来到的位置是cur,可变参数// 机器人还有rest步需要去走, 可变参数// 返回:机器人从cur出发,走过rest步之后,最终停在aim的方法数,是多少?// 当可变参数确定,返回值确定// 暴力递归版本 O(2^k)public static int process1(int N, int aim, int cur, int rest ) {if (rest == 0) { // 如果已经不需要走了,走完了! basecasereturn cur == aim ? 1 : 0; // 剩0步到达aim就是一种方法}// 还有路可以走// rest>0 ,来到1,必须1→2,还剩rest-1。if (cur == 1) { // 1 -> 2return process1(N ,aim, 2, rest - 1 );}// 来到N,没有选择只能N-1后退, 还剩rest-1if (cur == N) { // N-1 <- Nreturn process1(N ,aim, N - 1, rest - 1 );}// 机器人来到中间位置,有两种选择,往左迈一步,往右迈一步。return process1(N ,aim,cur - 1, rest - 1) + process1( N ,aim, cur + 1, rest - 1);}// 记忆化搜索,搞定可变参数组合 O(KxN)public static int ways2(int N, int start, int aim, int K) {if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) {return -1;}// 开多大分析可变参数范围,0~K,K+1, 1~N,N+1,0位置是无法到达的int[][] dp = new int[N + 1][K + 1];// 初始化都置成-1,不是-1就代表计算过,直接返回。for (int i = 0; i <= N; i++) {for (int j = 0; j <= K; j++) {dp[i][j] = -1;}}// dp就是缓存表// dp[cur][rest] == -1 -> process1(cur, rest)之前没算过!// dp[cur][rest] != -1 -> process1(cur, rest)之前算过!返回值,dp[cur][rest]// N+1 * K+1return process2(start, K, aim, N, dp);}// cur 范: 1 ~ N// rest 范:0 ~ Kpublic static int process2(int cur, int rest, int aim, int N, int[][] dp) {if (dp[cur][rest] != -1) { // 状态计算过返回return dp[cur][rest];}// 之前没算过!缓存没命中 尝试if (rest == 0) {dp[rest][cur] = cur == aim ? 1 : 0; // 记忆return dp[cur][rest];}// rest >0 有路可走if (cur == 1) {dp[rest][cur] = process2(2, rest - 1, aim, N, dp);// 记忆} else if (cur == N) {dp[rest][cur] = process2(N - 1, rest - 1, aim, N, dp);// 记忆} else {dp[rest][cur] = process2(cur - 1, rest - 1, aim, N, dp) + process2(cur + 1, rest - 1, aim, N, dp);// 记忆}return dp[cur][rest];}// DP 改递归代码从格子取值public static int ways3(int N, int start, int aim, int K) {if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || K < 1) {return -1;}int[][] dp = new int[N + 1][K + 1];dp[aim][0] = 1;for (int rest = 1; rest <= K; rest++) {dp[1][rest] = dp[2][rest - 1];for (int cur = 2; cur < N; cur++) {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];}
