From 4ae6c63b86689716220364d5dd7d09d50b6de36d Mon Sep 17 00:00:00 2001 From: Leo <582717189@qq.com> Date: Sat, 16 Jan 2021 18:35:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=83=E4=B9=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/leo/class22/KillMonster.java | 75 ++++++++++++++++++++++++- src/leo/class22/MinCoinsNoLimit.java | 69 +++++++++++++++++++++-- src/leo/class22/splitNumber.java | 82 +++++++++++++++++++++++++--- 3 files changed, 210 insertions(+), 16 deletions(-) diff --git a/src/leo/class22/KillMonster.java b/src/leo/class22/KillMonster.java index 1b20457..f489172 100644 --- a/src/leo/class22/KillMonster.java +++ b/src/leo/class22/KillMonster.java @@ -40,6 +40,53 @@ public class KillMonster { } + static class Recursion1 { + public static double kill(int n, int m, int k) { + if (n < 1 || m < 1 || k < 1) { + return 0; + } + long kill = process(n, m, k); + return (double) kill / Math.pow(m + 1, k); + } + + private static long process(int hp, int m, int rest) { + if (rest <= 0) { + return hp <= 0 ? 1 : 0; + } + if (hp <=0) { + return (long) Math.pow(m + 1, rest); + } + long ans = 0; + for (int i = 0; i <= m; i++) { + ans += process(hp - i, m, rest - 1); + } + return ans; + } + } + static class Dp1 { + public static double kill(int n, int m, int k) { + if (n < 1 || m < 1 || k < 1) { + return 0; + } + long[][] dp = new long[n + 1][k + 1]; + dp[0][0] = 1; + for (int hp = 1; hp <= n; hp++) { + for (int rest = 1; rest <= k; rest++) { + dp[0][rest] = (long) Math.pow(m + 1, rest); + long ans = 0; + for (int i = 0; i <= m; i++) { + if (hp - i > 0) { + ans += dp[hp - i][rest - 1]; + }else{ + ans += Math.pow(m + 1, rest - 1); + } + } + dp[hp][rest] = ans; + } + } + return (double)(dp[n][k] / Math.pow(m+1, k)); + } + } static class Dp { public static double kill(int n, int m, int k) { if (n < 1 || m < 1 || k < 1) { @@ -64,6 +111,28 @@ public class KillMonster { return dp[n][k] / Math.pow(m + 1, k); } } + static class OptDp1{ + public static double kill(int n, int m, int k) { + if (n < 1 || m < 1 || k < 1) { + return 0; + } + long[][] dp = new long[n + 1][k + 1]; + dp[0][0] = 1; + for (int hp = 1; hp <= n; hp++) { + for (int rest = 1; rest <= k; rest++) { + dp[0][rest] = (long) Math.pow(m + 1, rest); + dp[hp][rest] = dp[hp - 1][rest] + dp[hp][rest - 1]; + if (hp - m - 1 > 0) { + dp[hp][rest] -= dp[hp - m - 1][rest - 1]; + }else{ + dp[hp][rest] -= Math.pow(m + 1, rest - 1); + } + } + } + return dp[n][k] / Math.pow(m + 1, k); + } + } + static class OptDp{ public static double kill(int n, int m, int k) { if (n < 1 || m < 1 || k < 1) { @@ -97,9 +166,9 @@ public class KillMonster { int N = (int) (Math.random() * NMax); int M = (int) (Math.random() * MMax); int K = (int) (Math.random() * KMax); - double ans1 = Recursion.kill(N, M, K); - double ans2 = Dp.kill(N, M, K); - double ans3 = OptDp.kill(N, M, K); + double ans1 = Recursion1.kill(N, M, K); + double ans2 = Dp1.kill(N, M, K); + double ans3 = OptDp1.kill(N, M, K); if (ans1 != ans2 || ans1 != ans3) { System.out.println("Oops!"); break; diff --git a/src/leo/class22/MinCoinsNoLimit.java b/src/leo/class22/MinCoinsNoLimit.java index 47ed236..9f444fa 100644 --- a/src/leo/class22/MinCoinsNoLimit.java +++ b/src/leo/class22/MinCoinsNoLimit.java @@ -16,7 +16,6 @@ public class MinCoinsNoLimit { static class Recursion{ public static int minCoins(int[] arr, int aim) { - return process(arr, aim, 0); } @@ -35,6 +34,66 @@ public class MinCoinsNoLimit { } } + static class Recursion1 { + public static int minCoins(int[] arr, int aim) { + return process(arr, 0, aim); + } + private static int process(int[] arr, int i, int rest) { + if (i == arr.length) { + return rest == 0 ? 0 : Integer.MAX_VALUE; + } + int min = Integer.MAX_VALUE; + for (int z = 0; z * arr[i] <= rest; z++) { + int next = process(arr, i + 1, rest - z * arr[i]); + if (next != Integer.MAX_VALUE) { + min = Math.min(min, next + z); + } + } + return min; + } + } + static class Dp1{ + public static int minCoins(int[] arr, int aim) { + int n = arr.length; + int[][] dp = new int[n + 1][aim + 1]; + dp[n][0] = 0; + for (int i = 1; i <= aim; i++) { + dp[n][i] = Integer.MAX_VALUE; + } + for (int i = n - 1; i >= 0; i--) { + for (int rest = 0; rest <= aim; rest++) { + int min = Integer.MAX_VALUE; + for (int z = 0; z * arr[i] <= rest; z++) { + int next = dp[i + 1][rest - z * arr[i]]; + if (next != Integer.MAX_VALUE) { + min = Math.min(min, next + z); + } + } + dp[i][rest] = min; + } + } + return dp[0][aim]; + } + } + static class OptDp1 { + public static int minCoins(int[] arr, int aim) { + int n = arr.length; + int[][] dp = new int[n + 1][aim + 1]; + dp[n][0] = 0; + for (int i = 1; i <= aim; i++) { + dp[n][i] = Integer.MAX_VALUE; + } + for (int i = n - 1; i >= 0; i--) { + for (int rest = 0; rest <= aim; rest++) { + dp[i][rest] = dp[i + 1][rest]; + if (rest - arr[i] >= 0 && dp[i][rest - arr[i]] != Integer.MAX_VALUE) { + dp[i][rest] = Math.min(dp[i][rest], dp[i][rest - arr[i]] + 1); + } + } + } + return dp[0][aim]; + } + } static class Dp { public static int minCoins(int[] arr, int aim) { @@ -120,14 +179,14 @@ public class MinCoinsNoLimit { int N = (int) (Math.random() * maxLen); int[] arr = randomArray(N, maxValue); int aim = (int) (Math.random() * maxValue); - int ans1 = Recursion.minCoins(arr, aim); - int ans2 = Dp.minCoins(arr, aim); - int ans3 = OptDp.minCoins(arr, aim); + int ans1 = Recursion1.minCoins(arr, aim); + int ans2 = Dp1.minCoins(arr, aim); + int ans3 = OptDp1.minCoins(arr, aim); if (ans1 != ans2 || ans1 != ans3) { System.out.println("Oops!"); printArray(arr); System.out.println(aim); - System.out.println("--0---"); + System.out.println("-----"); System.out.println(ans1); System.out.println(ans2); System.out.println(ans3); diff --git a/src/leo/class22/splitNumber.java b/src/leo/class22/splitNumber.java index 38363cb..588a7a2 100644 --- a/src/leo/class22/splitNumber.java +++ b/src/leo/class22/splitNumber.java @@ -6,10 +6,10 @@ package leo.class22; * @DATE 2021/1/14 10:02 下午 * @Description * - * 给定一个正数1,裂开的方法有一种, - * (1) 给定一个正数2,裂开的方法有两种,(1和1)、 - * (2) 给定一个正数3,裂开的方法有三种,(1、1、1)、(1、2)、 - * (3) 给定一个正数4,裂开的方法有五种,(1、1、1、1)、(1、1、2)、(1、3)、(2、2)、 (4) + * 给定一个正数1,裂开的方法有一种,(1) + * 给定一个正数2,裂开的方法有两种,(1和1)、(2) + * 给定一个正数3,裂开的方法有三种,(1、1、1)、(1、2)、(3) + * 给定一个正数4,裂开的方法有五种,(1、1、1、1)、(1、1、2)、(1、3)、(2、2)、 (4) * 给定一个正数n,求裂开的方法数。 动态规划优化状态依赖的技巧 */ public class splitNumber { @@ -37,6 +37,73 @@ public class splitNumber { } + static class Recursion1{ + public static int number(int n) { + if (n <= 0) { + return 0; + } + return process(n, 1); + } + + private static int process(int rest, int pre) { + if (rest == 0) { + return 1; + } + if (pre >= rest) { + return rest - pre == 0 ? 1 : 0; + } + int ans = 0; + for (int i = pre; i <= rest; i++) { + ans += process(rest - i, i); + } + return ans; + } + } + + static class Dp1{ + public static int number(int n) { + if (n <= 0) { + return 0; + } + int[][] dp = new int[n + 1][n + 1]; + for (int i = 0; i <= n; i++) { + dp[i][i] = 1; + dp[i][0] = 1; + } + for (int pre = n-1; pre >=0; pre--) { + for (int rest = pre+1; rest <= n; rest++) { + int ans = 0; + for (int i = pre; i <= rest; i++) { + ans += dp[i][rest - i]; + } + dp[pre][rest] = ans; + } + } + return dp[0][n]; + } + } + + static class OptDp1{ + public static int number(int n) { + if (n <= 0) { + return 0; + } + int[][] dp = new int[n + 1][n + 1]; + for (int i = 1; i <= n; i++) { + dp[i][i] = 1; + dp[i][0] = 1; + } + for (int pre = n - 1; pre > 0; pre--) { + for (int rest = pre + 1; rest <= n; rest++) { + //下面的格子 + dp[pre][rest] = dp[pre+1][rest]; + //左侧的格子 + dp[pre][rest] += dp[pre][rest - pre]; + } + } + return dp[1][n]; + } + } static class Dp{ public static int number(int n) { if (n <= 0) { @@ -60,7 +127,6 @@ public class splitNumber { } } - static class OptDp{ public static int number(int n) { if (n <= 0) { @@ -84,9 +150,9 @@ public class splitNumber { } } public static void main(String[] args){ - System.out.println( Recursion.number(13)); - System.out.println(Dp.number(13)); - System.out.println(OptDp.number(13)); + System.out.println( Recursion1.number(14)); + System.out.println(Dp1.number(14)); + System.out.println(OptDp1.number(14)); } }