modify code

pull/6/head
左程云 4 years ago
parent a7f7f0bf19
commit 009a290767

@ -2,72 +2,78 @@ package class22;
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) {
@ -80,9 +86,9 @@ public class Code01_KillMonster {
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;

@ -6,10 +6,10 @@ public class Code02_MinCoinsNoLimit {
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 {
@ -17,14 +17,39 @@ public class Code02_MinCoinsNoLimit {
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;
}
@ -37,8 +62,10 @@ public class Code02_MinCoinsNoLimit {
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];
@ -77,8 +104,9 @@ public class Code02_MinCoinsNoLimit {
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);

@ -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));
}
}

@ -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) {

@ -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) {

@ -1,6 +1,6 @@
package class23;
public class Code01_NQueens {
public class Code03_NQueens {
public static int num1(int n) {
if (n < 1) {

@ -4,7 +4,7 @@ import java.util.HashMap;
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);
Loading…
Cancel
Save