From 08830762fe8fbeee96f60139e7b442fbe93af494 Mon Sep 17 00:00:00 2001 From: Leo <582717189@qq.com> Date: Wed, 6 Jan 2021 00:32:22 +0800 Subject: [PATCH] 18 --- src/leo/class18/CardsInLine.java | 147 +++++++++++++++++++++++++++++++ src/leo/class18/RobotWalk.java | 134 ++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 src/leo/class18/CardsInLine.java create mode 100644 src/leo/class18/RobotWalk.java diff --git a/src/leo/class18/CardsInLine.java b/src/leo/class18/CardsInLine.java new file mode 100644 index 0000000..4e3525b --- /dev/null +++ b/src/leo/class18/CardsInLine.java @@ -0,0 +1,147 @@ +package leo.class18; + +import class18.Code02_CardsInLine; +import org.w3c.dom.ranges.Range; + +/** + * @author Leo + * @ClassName CardsInLine + * @DATE 2021/1/5 11:48 下午 + * @Description + * 给定一个整型数组arr,代表数值不同的纸牌排成一条线, + * 玩家A和玩家B依次拿走每张纸牌, + * 规定玩家A先拿,玩家B后拿, + * 但是每个玩家每次只能拿走最左或最右的纸牌, + * 玩家A和玩家B都绝顶聪明。请返回最后获胜者的分数 + */ +public class CardsInLine { + + static class Recursion { + public static int win(int[] arr) { + if (arr.length == 0 || arr == null) { + return 0; + } + int f = f(arr, 0, arr.length - 1); + int g = g(arr, 0, arr.length - 1); + return Math.max(f, g); + } + + private static int g(int[] arr, int l, int r) { + if (l == r) { + return 0; + } + int p1 = f(arr, l + 1, r); + int p2 = f(arr, l, r - 1); + return Math.min(p1, p2); + } + + private static int f(int[] arr, int l, int r) { + if (l == r) { + return arr[l]; + } + int p1 = arr[l] + g(arr, l + 1, r); + int p2 = arr[r] + g(arr, l, r - 1); + return Math.max(p1, p2); + } + } + + static class RecursionDp { + public static int win(int[] arr) { + if (arr.length == 0 || arr == null) { + return 0; + } + int n = arr.length; + int[][] fDp = new int[n][n]; + int[][] gDp = new int[n][n]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + fDp[i][j] = -1; + gDp[i][j] = -1; + } + } + int f = f(arr, 0, arr.length - 1, fDp, gDp); + int g = g(arr, 0, arr.length - 1, fDp, gDp); + return Math.max(f, g); + } + + private static int f(int[] arr, int l, int r, int[][] fDp, int[][] gDp) { + if (fDp[l][r] != -1) { + return fDp[l][r]; + } + int ans = 0; + if (l == r) { + ans = arr[l]; + }else{ + int p1 = arr[l] + g(arr, l + 1, r, fDp, gDp); + int p2 = arr[r] + g(arr, l, r - 1, fDp, gDp); + ans = Math.max(p1, p2); + } + fDp[l][r] = ans; + return ans; + } + private static int g(int[] arr, int l, int r, int[][] fDp, int[][] gDp) { + if (gDp[l][r] != -1) { + return gDp[l][r]; + } + int ans = 0; + if (l < r) { + int p1 = f(arr, l + 1, r, fDp, gDp); + int p2 = f(arr, l, r - 1, fDp, gDp); + ans = Math.min(p1, p2); + } + gDp[l][r] = ans; + return ans; + } + } + + static class DP { + public static int win(int[] arr) { + if (arr.length == 0 || arr == null) { + return 0; + } + int n = arr.length; + int[][] fDp = new int[n][n]; + int[][] gDp = new int[n][n]; + for (int i = 0; i < n; i++) { + //当l==r时 fDp的状态 + fDp[i][i] = arr[i]; + } + //对角线的位置已经设置好了 + for (int startCol = 1; startCol < n; startCol++) { + int l = 0;//row + int r = startCol;//col + //防止列越界 + while (r < n) { + fDp[l][r] = Math.max(arr[l] + gDp[l + 1][r], arr[r] + gDp[l][r - 1]); + gDp[l][r] = Math.min(fDp[l + 1][r], fDp[l][r - 1]); + l++; + r++; + } + } + return Math.max(fDp[0][n - 1], gDp[0][n - 1]); + } + } + + + + public static void main(String[] args){ + int maxSize = 30; + int range = 60; + int[] arr = randomArray(maxSize, range); + + + System.out.println(Recursion.win(arr)); + System.out.println(RecursionDp.win(arr)); + System.out.println(DP.win(arr)); + } + + public static int[] randomArray(int maxSize, int range) { + int size = (int) (Math.random() * maxSize + 1); + int[] arr = new int[size]; + for (int i = 0; i < size; i++) { + arr[i] = (int) (range * Math.random() + 1); + } + return arr; + } + +} diff --git a/src/leo/class18/RobotWalk.java b/src/leo/class18/RobotWalk.java new file mode 100644 index 0000000..522791f --- /dev/null +++ b/src/leo/class18/RobotWalk.java @@ -0,0 +1,134 @@ +package leo.class18; + +import java.awt.event.KeyEvent; + +/** + * @author Leo + * @ClassName RobotWalk + * @DATE 2021/1/5 4:27 下午 + * @Description + */ +public class RobotWalk { + + static class Recursion { + /** + * 功能描述 : + * 一个机器人,从start出发, + * 走到aim,在走k步的情况下, + * 一共有多少种走法? + * @author Leo + * @date 2021/1/5 4:37 下午 + * @param N 一共多少路 + * @param start 起始点 + * @param aim 目标点 + * @param k 可以走几步 + * @return int + */ + public static int walk(int N, int start, int aim, int k) { + if (N < 2 || start < 1 || start > N || aim < 1 || aim > N || k < 1) { + return -1; + } + return process(start, k, aim, N); + } + + /** + * 功能描述 : + * 从cur出发,走了rest步后,最终到aim的方法数是多少? + * @param cur 当前位置 + * @param rest 还有多少步 + * @param aim 目标 + * @param N 一共有多少位置 + * @return int + * @author Leo + * @date 2021/1/5 4:49 下午 + */ + public static int process(int cur, int rest, int aim, int N) { + + if (rest == 0) { + return cur == aim ? 1 : 0; + } + if (cur == 1) { + return process(2, rest - 1, aim, N); + } + if (cur == N) { + return process(N - 1, rest - 1, aim, N); + } + return process(cur + 1, rest - 1, aim, N) + process(cur - 1, rest - 1, aim, N); + } + + + } + /** + * 从顶向下的动态规划(记忆化搜索) + */ + static class RecursionDp { + public static int walk(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]; + for (int i = 0; i < dp.length; i++) { + for (int j = 0; j < dp[i].length; j++) { + dp[i][j] = -1; + } + } + return process(start, k, aim, N, dp); + } + + private static int process(int cur, int rest, int aim, int n, int[][] dp) { + if (dp[cur][rest] != -1) { + return dp[cur][rest]; + } + int ans = 0; + if (rest == 0) { + ans = cur == aim ? 1 : 0; + } else if (cur == 1) { + ans = process(2, rest - 1, aim, n, dp); + } else if (cur == n) { + ans = process(n - 1, rest - 1, aim, n, dp); + }else { + ans = process(cur - 1, rest - 1, aim, n, dp) + process(cur + 1, rest - 1, aim, n, dp); + } + dp[cur][rest] = ans; + return ans; + } + + } + /** + * 状态转移 cur为行,rest为列 + * 动态规划是结果,不是原因 + */ + static class DP{ + public static int walk(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]; + //第0列的值 + 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]; + } + } + + + public static class walkMain { + public static void main(String[] args){ + int N = 5; + int start = 2; + int aim = 4; + int k = 6; + System.out.println(Recursion.walk(N, start, aim, k)); + System.out.println(RecursionDp.walk(N, start, aim, k)); + System.out.println(DP.walk(N, start, aim, k)); + + } + + } +}