pull/6/head
左程云 4 years ago
parent de2e3f6fb0
commit beb12faeef

@ -1,106 +0,0 @@
package class20;
public class Code01_CoinsWay {
// arr中都是正数且无重复值返回组成aim的方法数
public static int ways1(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
return process1(arr, 0, aim);
}
public static int process1(int[] arr, int index, int rest) {
if(index == arr.length) {
return rest == 0 ? 1 : 0 ;
}
int ways = 0;
for(int zhang = 0; zhang * arr[index] <= rest ;zhang++) {
ways += process1(arr, index + 1, rest - (zhang * arr[index]) );
}
return ways;
}
public static int ways2(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
int[][] dp = new int[arr.length+1][aim+1];
// 一开始所有的过程,都没有计算呢
// dp[..][..] = -1
for(int i = 0 ; i < dp.length; i++) {
for(int j = 0 ; j < dp[0].length; j++) {
dp[i][j] = -1;
}
}
return process2(arr, 0, aim , dp);
}
// 如果index和rest的参数组合是没算过的dp[index][rest] == -1
// 如果index和rest的参数组合是算过的dp[index][rest] > - 1
public static int process2(int[] arr,
int index, int rest,
int[][] dp) {
if(dp[index][rest] != -1) {
return dp[index][rest];
}
if(index == arr.length) {
dp[index][rest] = rest == 0 ? 1 :0;
return dp[index][rest];
}
int ways = 0;
for(int zhang = 0; zhang * arr[index] <= rest ;zhang++) {
ways += process2(arr, index + 1, rest - (zhang * arr[index]) , dp );
}
dp[index][rest] = ways;
return ways;
}
public static int ways3(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
int N = arr.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 1;// dp[N][1...aim] = 0;
for(int index = N - 1; index >= 0; index--) {
for(int rest = 0; rest <= aim; rest++) {
int ways = 0;
for(int zhang = 0; zhang * arr[index] <= rest ;zhang++) {
ways += dp[index + 1] [rest - (zhang * arr[index])];
}
dp[index][rest] = ways;
}
}
return dp[0][aim];
}
public static int ways4(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
int N = arr.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 1;// dp[N][1...aim] = 0;
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] += dp[index][rest - arr[index]];
}
}
}
return dp[0][aim];
}
public static void main(String[] args) {
int[] arr = { 5, 10,50,100 };
int sum = 1000;
System.out.println(ways1(arr, sum));
System.out.println(ways2(arr, sum));
System.out.println(ways3(arr, sum));
System.out.println(ways4(arr, sum));
}
}

@ -0,0 +1,79 @@
package class20;
// arr是货币数组其中的值都是正数每个值都认为是一张货币
// 即便是值相同的货币认为每一张都是独立且不同的,
// 返回组成aim的方法数
public class Code01_CoinsWayEveryPaperDifferent {
public static int coinWays(int[] arr, int aim) {
return process(arr, 0, aim);
}
public static int process(int[] arr, int index, int rest) {
if (rest < 0) {
return 0;
}
if (index == arr.length) {
return rest == 0 ? 1 : 0;
} else {
return process(arr, index + 1, rest) + process(arr, index + 1, rest - arr[index]);
}
}
public static int dp(int[] arr, int aim) {
if (aim == 0) {
return 1;
}
int N = arr.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 1;
for (int index = N - 1; index >= 0; index--) {
for (int rest = 0; rest <= aim; rest++) {
dp[index][rest] = dp[index + 1][rest] + (rest - arr[index] >= 0 ? dp[index + 1][rest - arr[index]] : 0);
}
}
return dp[0][aim];
}
// 为了测试
public static int[] randomArray(int maxLen, int maxValue) {
int N = (int) (Math.random() * maxLen);
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = (int) (Math.random() * maxValue) + 1;
}
return arr;
}
// 为了测试
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// 为了测试
public static void main(String[] args) {
int maxLen = 20;
int maxValue = 30;
int testTime = 1000000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int[] arr = randomArray(maxLen, maxValue);
int aim = (int) (Math.random() * maxValue);
int ans1 = coinWays(arr, aim);
int ans2 = dp(arr, aim);
if (ans1 == ans2) {
System.out.println("Oops!");
printArray(arr);
System.out.println(aim);
System.out.println(ans1);
System.out.println(ans2);
break;
}
}
System.out.println("测试结束");
}
}

@ -0,0 +1,109 @@
package class20;
// arr是面值数组其中的值都是正数且无重复值
// 每张面值可以用无限张返回组成aim的方法数
public class Code02_CoinsWayNoLimit {
public static int coinsWay(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
return process(arr, 0, aim);
}
public static int process(int[] arr, int index, int rest) {
if (index == arr.length) {
return rest == 0 ? 1 : 0;
}
int ways = 0;
for (int zhang = 0; zhang * arr[index] <= rest; zhang++) {
ways += process(arr, index + 1, rest - (zhang * arr[index]));
}
return ways;
}
public static int dp1(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
int N = arr.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 1;
for (int index = N - 1; index >= 0; index--) {
for (int rest = 0; rest <= aim; rest++) {
int ways = 0;
for (int zhang = 0; zhang * arr[index] <= rest; zhang++) {
ways += dp[index + 1][rest - (zhang * arr[index])];
}
dp[index][rest] = ways;
}
}
return dp[0][aim];
}
public static int dp2(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
int N = arr.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 1;
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] += dp[index][rest - arr[index]];
}
}
}
return dp[0][aim];
}
// 为了测试
public static int[] randomArray(int maxLen, int maxValue) {
int N = (int) (Math.random() * maxLen);
int[] arr = new int[N];
boolean[] has = new boolean[maxValue + 1];
for (int i = 0; i < N; i++) {
do {
arr[i] = (int) (Math.random() * maxValue) + 1;
} while (has[arr[i]]);
has[arr[i]] = true;
}
return arr;
}
// 为了测试
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// 为了测试
public static void main(String[] args) {
int maxLen = 10;
int maxValue = 30;
int testTime = 1000000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int[] arr = randomArray(maxLen, maxValue);
int aim = (int) (Math.random() * maxValue);
int ans1 = coinsWay(arr, aim);
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);
System.out.println(ans1);
System.out.println(ans2);
System.out.println(ans3);
break;
}
}
System.out.println("测试结束");
}
}

@ -0,0 +1,149 @@
package class20;
import java.util.HashMap;
import java.util.Map.Entry;
// arr是货币数组其中的值都是正数每个值都认为是一张货币
// 值相同的货币认为每一张都没有不同!
// 返回组成aim的方法数
public class Code03_CoinsWaySameValueSamePapper {
public static class Info {
public int[] coins;
public int[] zhangs;
public Info(int[] c, int[] z) {
coins = c;
zhangs = z;
}
}
public static Info getInfo(int[] arr) {
HashMap<Integer, Integer> counts = new HashMap<>();
for (int value : arr) {
if (!counts.containsKey(value)) {
counts.put(value, 1);
} else {
counts.put(value, counts.get(value) + 1);
}
}
int N = counts.size();
int[] coins = new int[N];
int[] zhangs = new int[N];
int index = 0;
for (Entry<Integer, Integer> entry : counts.entrySet()) {
coins[index] = entry.getKey();
zhangs[index++] = entry.getValue();
}
return new Info(coins, zhangs);
}
public static int coinsWay(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
Info info = getInfo(arr);
return process(info.coins, info.zhangs, 0, aim);
}
public static int process(int[] coins, int[] zhangs, int index, int rest) {
if (index == coins.length) {
return rest == 0 ? 1 : 0;
}
int ways = 0;
for (int zhang = 0; zhang * coins[index] <= rest && zhang <= zhangs[index]; zhang++) {
ways += process(coins, zhangs, index + 1, rest - (zhang * coins[index]));
}
return ways;
}
public static int dp1(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
Info info = getInfo(arr);
int[] coins = info.coins;
int[] zhangs = info.zhangs;
int N = coins.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 1;
for (int index = N - 1; index >= 0; index--) {
for (int rest = 0; rest <= aim; rest++) {
int ways = 0;
for (int zhang = 0; zhang * coins[index] <= rest && zhang <= zhangs[index]; zhang++) {
ways += dp[index + 1][rest - (zhang * coins[index])];
}
dp[index][rest] = ways;
}
}
return dp[0][aim];
}
public static int dp2(int[] arr, int aim) {
if (arr == null || arr.length == 0 || aim < 0) {
return 0;
}
Info info = getInfo(arr);
int[] coins = info.coins;
int[] zhangs = info.zhangs;
int N = coins.length;
int[][] dp = new int[N + 1][aim + 1];
dp[N][0] = 1;
for (int index = N - 1; index >= 0; index--) {
for (int rest = 0; rest <= aim; rest++) {
dp[index][rest] = dp[index + 1][rest];
if (rest - coins[index] >= 0) {
dp[index][rest] += dp[index][rest - coins[index]];
}
if (rest - coins[index] * (zhangs[index] + 1) >= 0) {
dp[index][rest] -= dp[index + 1][rest - coins[index] * (zhangs[index] + 1)];
}
}
}
return dp[0][aim];
}
// 为了测试
public static int[] randomArray(int maxLen, int maxValue) {
int N = (int) (Math.random() * maxLen);
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = (int) (Math.random() * maxValue) + 1;
}
return arr;
}
// 为了测试
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// 为了测试
public static void main(String[] args) {
int maxLen = 10;
int maxValue = 20;
int testTime = 1000000;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
int[] arr = randomArray(maxLen, maxValue);
int aim = (int) (Math.random() * maxValue);
int ans1 = coinsWay(arr, aim);
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);
System.out.println(ans1);
System.out.println(ans2);
System.out.println(ans3);
break;
}
}
System.out.println("测试结束");
}
}

@ -0,0 +1,265 @@
package class20;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map.Entry;
// arr中的每个值都代表一张钱
// arr中都是正数aim>=0返回组成aim的最小张数
public class Code04_MinCoinsOnePaper {
public static int minCoins(int[] arr, int aim) {
return process(arr, 0, aim);
}
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 p1 = process(arr, index + 1, rest);
int p2 = process(arr, index + 1, rest - arr[index]);
if (p2 != Integer.MAX_VALUE) {
p2++;
}
return Math.min(p1, p2);
}
}
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 p1 = dp[index + 1][rest];
int p2 = rest - arr[index] >= 0 ? dp[index + 1][rest - arr[index]] : Integer.MAX_VALUE;
if (p2 != Integer.MAX_VALUE) {
p2++;
}
dp[index][rest] = Math.min(p1, p2);
}
}
return dp[0][aim];
}
public static class Info {
public int[] coins;
public int[] zhangs;
public Info(int[] c, int[] z) {
coins = c;
zhangs = z;
}
}
public static Info getInfo(int[] arr) {
HashMap<Integer, Integer> counts = new HashMap<>();
for (int value : arr) {
if (!counts.containsKey(value)) {
counts.put(value, 1);
} else {
counts.put(value, counts.get(value) + 1);
}
}
int N = counts.size();
int[] coins = new int[N];
int[] zhangs = new int[N];
int index = 0;
for (Entry<Integer, Integer> entry : counts.entrySet()) {
coins[index] = entry.getKey();
zhangs[index++] = entry.getValue();
}
return new Info(coins, zhangs);
}
public static int dp2(int[] arr, int aim) {
if (aim == 0) {
return 0;
}
Info info = getInfo(arr);
int[] coins = info.coins;
int[] zhangs = info.zhangs;
int N = coins.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++) {
dp[index][rest] = dp[index + 1][rest];
for (int zhang = 1; zhang * coins[index] <= aim && zhang <= zhangs[index]; zhang++) {
if (rest - zhang * coins[index] >= 0
&& dp[index + 1][rest - zhang * coins[index]] != Integer.MAX_VALUE) {
dp[index][rest] = Math.min(dp[index][rest], zhang + dp[index + 1][rest - zhang * coins[index]]);
}
}
}
}
return dp[0][aim];
}
public static int dp3(int[] arr, int aim) {
if (aim == 0) {
return 0;
}
Info info = getInfo(arr);
int[] coins = info.coins;
int[] zhangs = info.zhangs;
int N = coins.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;
}
int max = Integer.MIN_VALUE;
for (int i = 0; i < N; i++) {
max = Math.max(max, coins[i]);
}
WindowBoss windows = new WindowBoss(max);
for (int index = N - 1; index >= 0; index--) {
windows.setDpCoinZhang(dp[index + 1], coins[index], zhangs[index]);
int rest = 0;
for (; rest < Math.min(aim + 1, coins[index]); rest++) {
windows.clearAdd(rest);
dp[index][rest] = dp[index + 1][rest];
}
for (; rest <= aim; rest++) {
windows.add(rest);
dp[index][rest] = windows.min(rest);
}
}
return dp[0][aim];
}
public static class WindowBoss {
public ArrayList<LinkedList<Integer>> windows;
private int[] dp;
private int coin;
private int zhang;
public WindowBoss(int maxValue) {
windows = new ArrayList<>();
for (int i = 0; i < maxValue; i++) {
windows.add(new LinkedList<>());
}
dp = null;
coin = 0;
zhang = 0;
}
public void setDpCoinZhang(int[] d, int c, int z) {
dp = d;
coin = c;
zhang = z;
}
private int offset(int pre, int cur) {
return (cur - pre) / coin;
}
public void clearAdd(int rest) {
int windowi = rest % coin;
windows.get(windowi).clear();
windows.get(windowi).addLast(rest);
}
public void add(int rest) {
LinkedList<Integer> window = windows.get(rest % coin);
while (!window.isEmpty() && (dp[window.peekLast()] == Integer.MAX_VALUE
|| dp[window.peekLast()] + offset(window.peekLast(), rest) >= dp[rest])) {
window.pollLast();
}
window.addLast(rest);
int overdue = rest - coin * (zhang + 1);
if (window.peekFirst() == overdue) {
window.pollFirst();
}
}
public int min(int rest) {
LinkedList<Integer> window = windows.get(rest % coin);
int minIndex = window.peekFirst();
return dp[minIndex] + offset(minIndex, rest);
}
}
// 为了测试
public static int[] randomArray(int N, int maxValue) {
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = (int) (Math.random() * maxValue) + 1;
}
return arr;
}
// 为了测试
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// 为了测试
public static void main(String[] args) {
int maxLen = 20;
int maxValue = 30;
int testTime = 300000;
System.out.println("功能测试开始");
for (int i = 0; i < testTime; i++) {
int N = (int) (Math.random() * maxLen);
int[] arr = randomArray(N, maxValue);
int aim = (int) (Math.random() * maxValue);
int ans1 = minCoins(arr, aim);
int ans2 = dp1(arr, aim);
int ans3 = dp2(arr, aim);
int ans4 = dp3(arr, aim);
if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) {
System.out.println("Oops!");
printArray(arr);
System.out.println(aim);
System.out.println(ans1);
System.out.println(ans2);
System.out.println(ans3);
System.out.println(ans4);
break;
}
}
System.out.println("功能测试结束");
System.out.println("==========");
System.out.println("性能测试开始");
// 当货币很少出现重复dp2较快
// 当货币大量出现重复dp3的优势明显
maxLen = 30000;
maxValue = 10;
int aim = 60000;
int[] arr = randomArray(maxLen, maxValue);
long start;
long end;
start = System.currentTimeMillis();
int ans2 = dp2(arr, aim);
end = System.currentTimeMillis();
System.out.println("dp2答案 : " + ans2 + ", dp2运行时间 : " + (end - start) + " ms");
start = System.currentTimeMillis();
int ans3 = dp3(arr, aim);
end = System.currentTimeMillis();
System.out.println("dp3答案 : " + ans3 + ", dp3运行时间 : " + (end - start) + " ms");
System.out.println("性能测试结束");
}
}

@ -0,0 +1,95 @@
package class20;
// arr是面值数组其中的值都是正数且无重复值
// 每张面值可以用无限张返回组成aim的最少货币数
public class Code05_MinCoinsNoLimit {
public static int minCoins(int[] arr, int aim) {
return process(arr, 0, aim);
}
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);
}
}
return ans;
}
}
public static int dp(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++) {
dp[index][rest] = dp[index + 1][rest];
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];
}
// 为了测试
public static int[] randomArray(int maxLen, int maxValue) {
int N = (int) (Math.random() * maxLen);
int[] arr = new int[N];
boolean[] has = new boolean[maxValue + 1];
for (int i = 0; i < N; i++) {
do {
arr[i] = (int) (Math.random() * maxValue) + 1;
} while (has[arr[i]]);
has[arr[i]] = true;
}
return arr;
}
// 为了测试
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// 为了测试
public static void main(String[] args) {
int maxLen = 20;
int maxValue = 30;
int testTime = 300000;
System.out.println("功能测试开始");
for (int i = 0; i < testTime; i++) {
int N = (int) (Math.random() * maxLen);
int[] arr = randomArray(N, maxValue);
int aim = (int) (Math.random() * maxValue);
int ans1 = minCoins(arr, aim);
int ans2 = dp(arr, aim);
if (ans1 != ans2) {
System.out.println("Oops!");
printArray(arr);
System.out.println(aim);
System.out.println(ans1);
System.out.println(ans2);
break;
}
}
System.out.println("功能测试结束");
}
}

@ -0,0 +1,55 @@
package class21;
public class Code01_BobDie {
public static double livePosibility1(int row, int col, int k, int N, int M) {
return (double) process(row, col, k, N, M) / Math.pow(4, k);
}
public static long process(int row, int col, int rest, int N, int M) {
if (row < 0 || row == N || col < 0 || col == M) {
return 0;
}
if (rest == 0) {
return 1;
}
long up = process(row - 1, col, rest - 1, N, M);
long down = process(row + 1, col, rest - 1, N, M);
long left = process(row, col - 1, rest - 1, N, M);
long right = process(row, col + 1, rest - 1, N, M);
return up + down + left + right;
}
public static double livePosibility2(int row, int col, int k, int N, int M) {
long[][][] dp = new long[N][M][k + 1];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
dp[i][j][0] = 1;
}
}
for (int rest = 1; rest <= k; rest++) {
for (int r = 0; r < N; r++) {
for (int c = 0; c < M; c++) {
dp[r][c][rest] = pick(dp, N, M, r - 1, c, rest - 1);
dp[r][c][rest] += pick(dp, N, M, r + 1, c, rest - 1);
dp[r][c][rest] += pick(dp, N, M, r, c - 1, rest - 1);
dp[r][c][rest] += pick(dp, N, M, r, c + 1, rest - 1);
}
}
}
return (double) dp[row][col][k] / Math.pow(4, k);
}
public static long pick(long[][][] dp, int N, int M, int r, int c, int rest) {
if (r < 0 || r == N || c < 0 || c == M) {
return 0;
}
return dp[r][c][rest];
}
public static void main(String[] args) {
System.out.println(livePosibility1(6, 6, 10, 50, 50));
System.out.println(livePosibility2(6, 6, 10, 50, 50));
}
}

@ -0,0 +1,95 @@
package class21;
// 题目描述看包里KillMonster.jpeg
public class Code02_KillMonster {
public static double right1(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);
return (double) ((double) kill / (double) all);
}
public static long process1(int N, int M, int K) {
if (K == 0) {
return N <= 0 ? 1 : 0;
}
long ways = 0;
for (int i = 0; i <= M; i++) {
ways += process1(N - i, M, K - 1);
}
return ways;
}
public static double right2(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));
}
return process2(N, M, K - 1) + process2(N - 1, M, K) - process2(N - M - 1, M, K - 1);
}
// 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) {
if (N < 1 || M < 1 || K < 1) {
return 0;
}
long[][] dp = new long[N + 1][K + 1];
// 特别注意dp[0][j]既表示原含义也表示M+1的j次方的值
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];
} else {
dp[i][j] -= dp[i - M - 1][j - 1];
}
}
}
return (double) ((double) dp[N][K] / (double) dp[0][K]);
}
public static void main(String[] args) {
int NMax = 10;
int MMax = 10;
int KMax = 10;
int testTime = 200;
System.out.println("测试开始");
for (int i = 0; i < testTime; i++) {
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);
if (ans1 != ans2 || ans1 != ans3) {
System.out.println("Oops!");
break;
}
}
System.out.println("测试结束");
}
}

@ -1,4 +1,4 @@
package class20; package class21;
import java.util.TreeSet; import java.util.TreeSet;
@ -8,7 +8,7 @@ import java.util.TreeSet;
* 便arr * 便arr
* *
* */ * */
public class Code02_SplitSumClosed { public class Code03_SplitSumClosed {
public static int right(int[] arr) { public static int right(int[] arr) {
if (arr == null || arr.length < 2) { if (arr == null || arr.length < 2) {

@ -1,4 +1,4 @@
package class20; package class21;
import java.util.TreeSet; import java.util.TreeSet;
@ -11,7 +11,7 @@ import java.util.TreeSet;
* 便arr * 便arr
* *
* */ * */
public class Code03_SplitSumClosedSizeHalf { public class Code04_SplitSumClosedSizeHalf {
public static int right(int[] arr) { public static int right(int[] arr) {
if (arr == null || arr.length < 2) { if (arr == null || arr.length < 2) {

@ -1,6 +1,6 @@
package class20; package class21;
public class Code04_NQueens { public class Code05_NQueens {
public static int num1(int n) { public static int num1(int n) {
if (n < 1) { if (n < 1) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Loading…
Cancel
Save