Skip to content

Commit

Permalink
modify code
Browse files Browse the repository at this point in the history
  • Loading branch information
algorithmzuo committed Jan 14, 2021
1 parent a7f7f0b commit 009a290
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 54 deletions.
86 changes: 46 additions & 40 deletions src/class22/Code01_KillMonster.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,78 @@

public class Code01_KillMonster {

public static double right1(int N, int M, int K) {
public static double right(int N, int M, int K) {
if (N < 1 || M < 1 || K < 1) {
return 0;
}
long all = (long) Math.pow(M + 1, K);
long kill = process1(N, M, K);
long kill = process(K, M, N);
return (double) ((double) kill / (double) all);
}

public static long process1(int N, int M, int K) {
if (K == 0) {
return N <= 0 ? 1 : 0;
// 怪兽还剩hp点血
// 每次的伤害在[0~M]范围上
// 还有times次可以砍
// 返回砍死的情况数!
public static long process(int times, int M, int hp) {
if (times == 0) {
return hp <= 0 ? 1 : 0;
}
if (hp <= 0) {
return (long) Math.pow(M + 1, times);
}
long ways = 0;
for (int i = 0; i <= M; i++) {
ways += process1(N - i, M, K - 1);
ways += process(times - 1, M, hp - i);
}
return ways;
}

public static double right2(int N, int M, int K) {
public static double dp1(int N, int M, int K) {
if (N < 1 || M < 1 || K < 1) {
return 0;
}
long all = (long) Math.pow(M + 1, K);
long kill = process2(N, M, K);
return (double) ((double) kill / (double) all);
}

public static long process2(int N, int M, int K) {
if (K == 0) {
return N <= 0 ? 1 : 0;
}
if (N <= 0) {
return (long) (Math.pow(M + 1, K));
long[][] dp = new long[K + 1][N + 1];
dp[0][0] = 1;
for (int times = 1; times <= K; times++) {
dp[times][0] = (long) Math.pow(M + 1, times);
for (int hp = 1; hp <= N; hp++) {
long ways = 0;
for (int i = 0; i <= M; i++) {
if (hp - i >= 0) {
ways += dp[times - 1][hp - i];
} else {
ways += (long) Math.pow(M + 1, times - 1);
}
}
dp[times][hp] = ways;
}
}
return process2(N, M, K - 1) + process2(N - 1, M, K) - process2(N - M - 1, M, K - 1);
long kill = dp[K][N];
return (double) ((double) kill / (double) all);
}

// M = 5
// 以下为斜率优化改进枚举行为的动态规划
// dp[8][5] = dp[8..3][4]
// dp[9][5] = dp[9..4][4] = dp[9][4] + dp[8][5] - dp[3][4]
// 可以推出
// dp[i][j] = dp[i][j-1] + dp[i-1][j] - dp[i - M - 1][j-1]
public static double dp(int N, int M, int K) {
public static double dp2(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][j]既表示原含义,也表示M+1的j次方的值
long all = (long) Math.pow(M + 1, K);
long[][] dp = new long[K + 1][N + 1];
dp[0][0] = 1;
for (int j = 1; j <= K; j++) {
dp[0][j] = dp[0][j - 1] * (M + 1);
}
for (int j = 1; j <= K; j++) {
for (int i = 1; i <= N; i++) {
dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
if (i - M - 1 < 0) {
dp[i][j] -= dp[0][j - 1];
for (int times = 1; times <= K; times++) {
dp[times][0] = (long) Math.pow(M + 1, times);
for (int hp = 1; hp <= N; hp++) {
dp[times][hp] = dp[times][hp - 1] + dp[times - 1][hp];
if (hp - 1 - M >= 0) {
dp[times][hp] -= dp[times - 1][hp - 1 - M];
} else {
dp[i][j] -= dp[i - M - 1][j - 1];
dp[times][hp] -= Math.pow(M + 1, times - 1);
}
}
}
return (double) ((double) dp[N][K] / (double) dp[0][K]);
long kill = dp[K][N];
return (double) ((double) kill / (double) all);
}

public static void main(String[] args) {
Expand All @@ -80,9 +86,9 @@ public static void main(String[] args) {
int N = (int) (Math.random() * NMax);
int M = (int) (Math.random() * MMax);
int K = (int) (Math.random() * KMax);
double ans1 = right1(N, M, K);
double ans2 = right2(N, M, K);
double ans3 = dp(N, M, K);
double ans1 = right(N, M, K);
double ans2 = dp1(N, M, K);
double ans3 = dp2(N, M, K);
if (ans1 != ans2 || ans1 != ans3) {
System.out.println("Oops!");
break;
Expand Down
44 changes: 36 additions & 8 deletions src/class22/Code02_MinCoinsNoLimit.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,50 @@ public static int minCoins(int[] arr, int aim) {
return process(arr, 0, aim);
}

// arr[index...]面值,每种面值张数自由选择,
// 搞出rest正好这么多钱,返回最小张数
// 拿Integer.MAX_VALUE标记怎么都搞定不了
public static int process(int[] arr, int index, int rest) {
if (rest < 0) {
return Integer.MAX_VALUE;
}
if (index == arr.length) {
return rest == 0 ? 0 : Integer.MAX_VALUE;
} else {
int ans = Integer.MAX_VALUE;
for (int zhang = 0; zhang * arr[index] <= rest; zhang++) {
int next = process(arr, index + 1, rest - zhang * arr[index]);
if (next != Integer.MAX_VALUE) {
ans = Math.min(ans, next + zhang);
ans = Math.min(ans, zhang + next);
}
}
return ans;
}
}

public static int dp(int[] arr, int aim) {
public static int dp1(int[] arr, int aim) {
if (aim == 0) {
return 0;
}
int N = arr.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 0;
for (int j = 1; j <= aim; j++) {
dp[N][j] = Integer.MAX_VALUE;
}
for (int index = N - 1; index >= 0; index--) {
for (int rest = 0; rest <= aim; rest++) {
int ans = Integer.MAX_VALUE;
for (int zhang = 0; zhang * arr[index] <= rest; zhang++) {
int next = dp[index + 1][rest - zhang * arr[index]];
if (next != Integer.MAX_VALUE) {
ans = Math.min(ans, zhang + next);
}
}
dp[index][rest] = ans;
}
}
return dp[0][aim];
}

public static int dp2(int[] arr, int aim) {
if (aim == 0) {
return 0;
}
Expand All @@ -37,8 +62,10 @@ public static int dp(int[] arr, int aim) {
for (int index = N - 1; index >= 0; index--) {
for (int rest = 0; rest <= aim; rest++) {
dp[index][rest] = dp[index + 1][rest];
if (rest - arr[index] >= 0 && dp[index][rest - arr[index]] != Integer.MAX_VALUE)
if (rest - arr[index] >= 0
&& dp[index][rest - arr[index]] != Integer.MAX_VALUE) {
dp[index][rest] = Math.min(dp[index][rest], dp[index][rest - arr[index]] + 1);
}
}
}
return dp[0][aim];
Expand Down Expand Up @@ -77,8 +104,9 @@ public static void main(String[] args) {
int[] arr = randomArray(N, maxValue);
int aim = (int) (Math.random() * maxValue);
int ans1 = minCoins(arr, aim);
int ans2 = dp(arr, aim);
if (ans1 != ans2) {
int ans2 = dp1(arr, aim);
int ans3 = dp2(arr, aim);
if (ans1 != ans2 || ans1 != ans3) {
System.out.println("Oops!");
printArray(arr);
System.out.println(aim);
Expand Down
85 changes: 85 additions & 0 deletions src/class22/Code03_SplitNumber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package class22;

public class Code03_SplitNumber {

// n为正数
public static int ways(int n) {
if (n < 0) {
return 0;
}
if (n == 1) {
return 1;
}
return process(1, n);
}

// 上一个拆出来的数是pre
// 还剩rest需要去拆
// 返回拆解的方法数
public static int process(int pre, int rest) {
if (rest == 0) {
return 1;
}
if (pre > rest) {
return 0;
}
int ways = 0;
for (int first = pre; first <= rest; first++) {
ways += process(first, rest - first);
}
return ways;
}

public static int dp1(int n) {
if (n < 0) {
return 0;
}
if (n == 1) {
return 1;
}
int[][] dp = new int[n + 1][n + 1];
for (int pre = 1; pre <= n; pre++) {
dp[pre][0] = 1;
dp[pre][pre] = 1;
}
for (int pre = n - 1; pre >= 1; pre--) {
for (int rest = pre + 1; rest <= n; rest++) {
int ways = 0;
for (int first = pre; first <= rest; first++) {
ways += dp[first][rest - first];
}
dp[pre][rest] = ways;
}
}
return dp[1][n];
}

public static int dp2(int n) {
if (n < 0) {
return 0;
}
if (n == 1) {
return 1;
}
int[][] dp = new int[n + 1][n + 1];
for (int pre = 1; pre <= n; pre++) {
dp[pre][0] = 1;
dp[pre][pre] = 1;
}
for (int pre = n - 1; pre >= 1; 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];
}

public static void main(String[] args) {
int test = 39;
System.out.println(ways(test));
System.out.println(dp1(test));
System.out.println(dp2(test));
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package class22;
package class23;

import java.util.TreeSet;

public class Code03_SplitSumClosed {
public class Code01_SplitSumClosed {

public static int right(int[] arr) {
if (arr == null || arr.length < 2) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package class22;
package class23;

import java.util.TreeSet;

public class Code04_SplitSumClosedSizeHalf {
public class Code02_SplitSumClosedSizeHalf {

public static int right(int[] arr) {
if (arr == null || arr.length < 2) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package class23;

public class Code01_NQueens {
public class Code03_NQueens {

public static int num1(int n) {
if (n < 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.Map.Entry;
import java.util.LinkedList;

public class Code02_MinCoinsOnePaper {
public class Code04_MinCoinsOnePaper {

public static int minCoins(int[] arr, int aim) {
return process(arr, 0, aim);
Expand Down

0 comments on commit 009a290

Please sign in to comment.