暴力递归到动态规划
题目
象棋中马的跳法
机器人达到指定位置方法数
换钱的最少货币数
Bob的生存概率
纸牌问题
象棋中马的跳法
【题目】
请同学们自行搜索或者想象一个象棋的棋盘,然后把整个棋盘放入第一象限,棋盘的最左下 角是(0,0)位置。
那么整个棋盘就是横坐标上9条线、纵坐标上10条线的一个区域。
给你三个 参数,x,y,k,返回如果“马”从(0,0)位置出发,必须走k步,最后落在(x,y)上的方法数 有多少种?
暴力递归
思路:
定义一个8*9的棋盘,然后边界限制,不能跳的超出棋盘
当step 步数到0的时候,i,j 的位置也到达了 目标位置 a,b的时候,表示为一种有效方法
然后调递归不断的尝试,一共8个位置。
int process(int i, int j, int step,int a,int b) { if (i < 0 || i > 8 || j < 0 || j > 9) { return 0; } if (step == 0) { return (i == a && j == b) ? 1 : 0; } return process(i - 1, j - 2, step - 1, a, b) + process(i - 2, j - 1, step - 1, a, b) + process(i - 2, j + 1, step - 1, a, b) + process(i - 1, j + 2, step - 1, a, b) + process(i + 1, j - 2, step - 1, a, b) + process(i + 2, j - 1, step - 1, a, b) + process(i + 2, j + 1, step - 1, a, b) + process(i + 1, j + 2, step - 1, a, b); }
动态规划
int getValue(int ***dp, int i, int j,int step) { if (i < 0 || i>9 || j < 0 || j>8) { return 0; } return dp[i][j][step]; } int waydp(int a, int b, int s) { int ***dp = new int**[10]; for (int i = 0; i < 10; i++) { dp[i] = new int*[9]; for (int j = 0; j < 9; j++) { dp[i][j] = new int[s + 1]; } } for (int i = 0; i < 10; i++) { for (int j = 0; j < 9; j++) { for (int t = 0; t <= s; t++) { dp[i][j][t] = 0; } } } dp[a][b][0] = 1; for (int step = 1; step <= s; step++) { for (int i = 0; i < 10; i++) { for (int j = 0; j < 9; j++) { dp[i][j][step] = getValue(dp, i -1, j - 2, step - 1 ) + getValue(dp, i -2, j - 1, step - 1 ) + getValue(dp, i -2, j + 1, step - 1 ) + getValue(dp, i -1, j + 2, step - 1 ) + getValue(dp, i + 1, j - 2, step - 1 ) + getValue(dp, i + 2, j - 1, step - 1 ) + getValue(dp, i + 2, j + 1, step - 1 ) + getValue(dp, i + 1, j + 2, step - 1 ); } } } return dp[0][0][s]; }
机器人达到指定位置方法数
【题目】 假设有排成一行的 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。
暴力递归
//暴力递归 int way1(int n, int start, int end, int k) { if (k == 0) { return start == end ? 1 : 0; } if (start == 1) { return way1(n, 2, end, k - 1); } if (start == n) { return way1(n, n - 1, end, k - 1); } return way1(n, start + 1, end, k - 1) + way1(n, start - 1, end, k - 1); }
记忆化搜索
//记忆化搜索 int way2(int n, int start, int end, int k,int *dp[]) { if (dp[start][k] != -1) { return dp[start][k]; } int ans = 0; if (k == 0) { ans = start == end ? 1 : 0; dp[start][k] = ans; return ans; } if (start == 1) { ans = way2(n, 2, end, k - 1, dp); dp[start][k] = ans; return ans; } if (start == n) { ans = way2(n, n - 1, end, k - 1, dp); dp[start][k] = ans; return ans; } ans = way2(n, start + 1, end, k - 1, dp) + way2(n, start - 1, end, k - 1, dp); dp[start][k] = ans; return ans; } int f2(int n, int start, int end, int k) { int **dp = new int*[n + 1]; for (int i = 0; i < n + 1; i++) { dp[i] = new int[k + 1]; } for (int i = 0; i < n + 1; i++) { for (int j = 0; j < k + 1; j++) { dp[i][j] = -1; } } return way2(n, start, end, k, dp); }
动态规划
//动态规划 int waydp(int n, int start, int end, int k, int *dp[]) { dp[end][0] = 1; for (int col = 1; col <= k; col++) { dp[1][col] = dp[2][col - 1]; dp[n][col] = dp[n - 1][col - 1]; for (int row = 2; row < n; row++) { dp[row][col] = dp[row - 1][col - 1] + dp[row + 1][col - 1]; } } return dp[start][k]; } int f3(int n, int start, int end, int k) { int **dp = new int*[n + 1]; for (int i = 0; i < n + 1; i++) { dp[i] = new int[k + 1]; } for (int i = 0; i < n + 1; i++) { for (int j = 0; j < k + 1; j++) { dp[i][j] = 0; } } return waydp(n, start, end, k, dp); }
换钱的最少货币数
【题目】 给定数组 arr,arr 中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值 的货币可以使用任意张,再给定一个整数 aim,代表要找的钱数,求组成 aim 的最少货币 数。
【举例】 arr=[5,2,3],aim=20。 4 张 5 元可以组成 20 元,其他的找钱方案都要使用更多张的货币,所以返回 4。 arr=[5,2,3],aim=0。 不用任何货币就可以组成 0 元,返回 0。 arr=[3,5],aim=2。 根本无法组成 2 元,钱不能找开的情况下默认返回-1。
暴力递归
int process(int array[], int index, int aim,int len) { if (index == len) { return aim == 0 ? 1 : 0; } int ways = 0; for (int zhang = 0; zhang*array[index] <= aim; zhang++) { ways += process(array, index + 1, aim - zhang * array[index],len); } return ways; }
Bob的生存概率
【题目】 给定五个参数n,m,i,j,k。表示在一个N*M的区域,Bob处在(i,j)点,每次Bob等概率的向上、 下、左、右四个方向移动一步,Bob必须走K步。如果走完之后,Bob还停留在这个区域上, 就算Bob存活,否则就算Bob死亡。请求解Bob的生存概率,返回字符串表示分数的方式。
暴力递归
int process(int i, int j, int n, int m, int k) { if (n < 0 || i == n || m < 0 || j == m) { return 0; } if (k == 0) { return 1; } int live = process(i, j, n - 1, m, k - 1) + process(i, j, n + 1, m, k - 1) + process(i, j, n, m + 1, k - 1) + process(i, j, n, m - 1, k - 1); return live; }
动态规划
long gcd(long m, long n) { return n == 0 ? m : gcd(n, m%n); } void waydp(int N, int M, int i, int j, int rest) { int ***dp = new int**[N+2]; for (int i = 0; i < N + 2; i++) { dp[i] = new int*[M + 2]; for (int j = 0; j < M + 2; j++) { dp[i][j] = new int[rest + 1]; } } for (int i = 0; i < N + 2; i++) { for (int j = 0; j < M + 2; j++) { for (int k = 0; k < rest + 1; k++) { dp[i][j][k] = 0; } dp[i][j][0] = 1; } } for (int k = 1; k <= rest; k++) { for (int row = 1; row <= N; row++) { for (int col = 1; col <= M; col++) { dp[row][col][k] = dp[row + 1][col][k - 1]; dp[row][col][k] += dp[row - 1][col][k - 1]; dp[row][col][k] += dp[row][col + 1][k - 1]; dp[row][col][k] += dp[row][col - 1][k - 1]; } } } long all = (long)pow(4, rest); long live = dp[i + 1][j + 1][rest]; long gcdd = gcd(all, live); cout << (live / gcdd) << "/" << (all / gcdd); }
纸牌问题
暴力递归
int f(int arr[], int L, int R) { if (L == R) { return arr[L]; } return max(arr[L] + s(arr, L + 1, R), arr[R] + s(arr, L, R - 1)); } int s(int arr[], int L, int R) { if (L == R) { return 0; } return min(f(arr, L + 1, R), f(arr, L, R - 1)); }
动态规划
int waydp(int arr[], int L, int R,int len) { if (len == 0) { return 0; } int **f = new int*[len]; int **s = new int*[len]; for (int i = 0; i < len; i++) { f[i] = new int[len]; s[i] = new int[len]; } for (int i = 0; i < len; i++) { f[i][i] = arr[i]; s[i][i] = 0; } for (int col = 1; col < len; col++) { int i = 0; int j = col; while (i < len&&j < len) { f[i][j] = max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]); s[i][j] = min(f[i + 1][j], f[i][j - 1]); i++; j++; } } return max(f[0][len - 1], s[0][len - 1]); }

浙公网安备 33010602011771号