modify code

pull/6/head
左程云 5 years ago
parent d13b2a1c22
commit 78e5dc4d7c

@ -10,14 +10,17 @@ public class Code01_SplitSumClosed {
for (int num : arr) { for (int num : arr) {
sum += num; sum += num;
} }
return process(arr, 0, sum >> 1); return process(arr, 0, sum / 2);
} }
// arr[i...]可以自由选择请返回累加和尽量接近rest但不能超过rest的情况下最接近的累加和是多少
public static int process(int[] arr, int i, int rest) { public static int process(int[] arr, int i, int rest) {
if (i == arr.length) { if (i == arr.length) {
return 0; return 0;
} else { } else { // 还有数arr[i]这个数
// 可能性1不使用arr[i]
int p1 = process(arr, i + 1, rest); int p1 = process(arr, i + 1, rest);
// 可能性2要使用arr[i]
int p2 = 0; int p2 = 0;
if (arr[i] <= rest) { if (arr[i] <= rest) {
p2 = arr[i] + process(arr, i + 1, rest - arr[i]); p2 = arr[i] + process(arr, i + 1, rest - arr[i]);
@ -34,29 +37,22 @@ public class Code01_SplitSumClosed {
for (int num : arr) { for (int num : arr) {
sum += num; sum += num;
} }
sum >>= 1; sum /= 2;
int N = arr.length; int N = arr.length;
boolean[][] dp = new boolean[N][sum + 1]; int[][] dp = new int[N + 1][sum + 1];
for (int i = 0; i < N; i++) { for (int i = N - 1; i >= 0; i--) {
dp[i][0] = true; for (int rest = 0; rest <= sum; rest++) {
} // 可能性1不使用arr[i]
if (arr[0] <= sum) { int p1 = dp[i + 1][rest];
dp[0][arr[0]] = true; // 可能性2要使用arr[i]
} int p2 = 0;
for (int i = 1; i < N; i++) { if (arr[i] <= rest) {
for (int j = 1; j <= sum; j++) { p2 = arr[i] + dp[i + 1][rest - arr[i]];
dp[i][j] = dp[i - 1][j];
if (j - arr[i] >= 0) {
dp[i][j] |= dp[i - 1][j - arr[i]];
} }
dp[i][rest] = Math.max(p1, p2);
} }
} }
for (int j = sum; j >= 1; j--) { return dp[0][sum];
if (dp[N - 1][j]) {
return j;
}
}
return 0;
} }
public static int[] randomArray(int len, int value) { public static int[] randomArray(int len, int value) {

@ -10,30 +10,33 @@ public class Code02_SplitSumClosedSizeHalf {
for (int num : arr) { for (int num : arr) {
sum += num; sum += num;
} }
return process(arr, 0, 0, sum >> 1); if ((arr.length & 1) == 0) {
return process(arr, 0, arr.length / 2, sum / 2);
} else {
return Math.max(process(arr, 0, arr.length / 2, sum / 2), process(arr, 0, arr.length / 2 + 1, sum / 2));
}
} }
// arr[i....]自由选择挑选的个数一定要是picks个累加和<=rest, 离rest最近的返回
public static int process(int[] arr, int i, int picks, int rest) { public static int process(int[] arr, int i, int picks, int rest) {
if (i == arr.length) { if (i == arr.length) {
if ((arr.length & 1) == 0) { return picks == 0 ? 0 : -1;
return picks == (arr.length >> 1) ? 0 : -1; } else {
} else { int p1 = process(arr, i + 1, picks, rest);
return (picks == (arr.length >> 1) || picks == (arr.length >> 1) + 1) ? 0 : -1; // 就是要使用arr[i]这个数
int p2 = -1;
int next = -1;
if (arr[i] <= rest) {
next = process(arr, i + 1, picks - 1, rest - arr[i]);
} }
if (next != -1) {
p2 = arr[i] + next;
}
return Math.max(p1, p2);
} }
int p1 = process(arr, i + 1, picks, rest);
int p2 = -1;
int next2 = -1;
if (arr[i] <= rest) {
next2 = process(arr, i + 1, picks + 1, rest - arr[i]);
}
if (next2 != -1) {
p2 = arr[i] + next2;
}
return Math.max(p1, p2);
} }
public static int dp1(int[] arr) { public static int dp(int[] arr) {
if (arr == null || arr.length < 2) { if (arr == null || arr.length < 2) {
return 0; return 0;
} }
@ -41,9 +44,9 @@ public class Code02_SplitSumClosedSizeHalf {
for (int num : arr) { for (int num : arr) {
sum += num; sum += num;
} }
sum >>= 1; sum /= 2;
int N = arr.length; int N = arr.length;
int M = (arr.length + 1) >> 1; int M = (N + 1) / 2;
int[][][] dp = new int[N + 1][M + 1][sum + 1]; int[][][] dp = new int[N + 1][M + 1][sum + 1];
for (int i = 0; i <= N; i++) { for (int i = 0; i <= N; i++) {
for (int j = 0; j <= M; j++) { for (int j = 0; j <= M; j++) {
@ -52,33 +55,110 @@ public class Code02_SplitSumClosedSizeHalf {
} }
} }
} }
for (int k = 0; k <= sum; k++) { for (int rest = 0; rest <= sum; rest++) {
dp[N][M][k] = 0; dp[N][0][rest] = 0;
}
if ((arr.length & 1) != 0) {
for (int k = 0; k <= sum; k++) {
dp[N][M - 1][k] = 0;
}
} }
for (int i = N - 1; i >= 0; i--) { for (int i = N - 1; i >= 0; i--) {
for (int picks = 0; picks <= M; picks++) { for (int picks = 0; picks <= M; picks++) {
for (int rest = 0; rest <= sum; rest++) { for (int rest = 0; rest <= sum; rest++) {
int p1 = dp[i + 1][picks][rest]; int p1 = dp[i + 1][picks][rest];
// 就是要使用arr[i]这个数
int p2 = -1; int p2 = -1;
int next2 = -1; int next = -1;
if (picks + 1 <= M && arr[i] <= rest) { if (picks - 1 >= 0 && arr[i] <= rest) {
next2 = dp[i + 1][picks + 1][rest - arr[i]]; next = dp[i + 1][picks - 1][rest - arr[i]];
} }
if (next2 != -1) { if (next != -1) {
p2 = arr[i] + next2; p2 = arr[i] + next;
} }
dp[i][picks][rest] = Math.max(p1, p2); dp[i][picks][rest] = Math.max(p1, p2);
} }
} }
} }
return dp[0][0][sum]; if ((arr.length & 1) == 0) {
return dp[0][arr.length / 2][sum];
} else {
return Math.max(dp[0][arr.length / 2][sum], dp[0][(arr.length / 2) + 1][sum]);
}
} }
// public static int right(int[] arr) {
// if (arr == null || arr.length < 2) {
// return 0;
// }
// int sum = 0;
// for (int num : arr) {
// sum += num;
// }
// return process(arr, 0, 0, sum >> 1);
// }
//
// public static int process(int[] arr, int i, int picks, int rest) {
// if (i == arr.length) {
// if ((arr.length & 1) == 0) {
// return picks == (arr.length >> 1) ? 0 : -1;
// } else {
// return (picks == (arr.length >> 1) || picks == (arr.length >> 1) + 1) ? 0 : -1;
// }
// }
// int p1 = process(arr, i + 1, picks, rest);
// int p2 = -1;
// int next2 = -1;
// if (arr[i] <= rest) {
// next2 = process(arr, i + 1, picks + 1, rest - arr[i]);
// }
// if (next2 != -1) {
// p2 = arr[i] + next2;
// }
// return Math.max(p1, p2);
// }
//
// public static int dp1(int[] arr) {
// if (arr == null || arr.length < 2) {
// return 0;
// }
// int sum = 0;
// for (int num : arr) {
// sum += num;
// }
// sum >>= 1;
// int N = arr.length;
// int M = (arr.length + 1) >> 1;
// int[][][] dp = new int[N + 1][M + 1][sum + 1];
// for (int i = 0; i <= N; i++) {
// for (int j = 0; j <= M; j++) {
// for (int k = 0; k <= sum; k++) {
// dp[i][j][k] = -1;
// }
// }
// }
// for (int k = 0; k <= sum; k++) {
// dp[N][M][k] = 0;
// }
// if ((arr.length & 1) != 0) {
// for (int k = 0; k <= sum; k++) {
// dp[N][M - 1][k] = 0;
// }
// }
// for (int i = N - 1; i >= 0; i--) {
// for (int picks = 0; picks <= M; picks++) {
// for (int rest = 0; rest <= sum; rest++) {
// int p1 = dp[i + 1][picks][rest];
// int p2 = -1;
// int next2 = -1;
// if (picks + 1 <= M && arr[i] <= rest) {
// next2 = dp[i + 1][picks + 1][rest - arr[i]];
// }
// if (next2 != -1) {
// p2 = arr[i] + next2;
// }
// dp[i][picks][rest] = Math.max(p1, p2);
// }
// }
// }
// return dp[0][0][sum];
// }
public static int dp2(int[] arr) { public static int dp2(int[] arr) {
if (arr == null || arr.length < 2) { if (arr == null || arr.length < 2) {
return 0; return 0;
@ -138,7 +218,7 @@ public class Code02_SplitSumClosedSizeHalf {
// for test // for test
public static void main(String[] args) { public static void main(String[] args) {
int maxLen = 20; int maxLen = 10;
int maxValue = 50; int maxValue = 50;
int testTime = 10000; int testTime = 10000;
System.out.println("测试开始"); System.out.println("测试开始");
@ -146,7 +226,7 @@ public class Code02_SplitSumClosedSizeHalf {
int len = (int) (Math.random() * maxLen); int len = (int) (Math.random() * maxLen);
int[] arr = randomArray(len, maxValue); int[] arr = randomArray(len, maxValue);
int ans1 = right(arr); int ans1 = right(arr);
int ans2 = dp1(arr); int ans2 = dp(arr);
int ans3 = dp2(arr); int ans3 = dp2(arr);
if (ans1 != ans2 || ans1 != ans3) { if (ans1 != ans2 || ans1 != ans3) {
printArray(arr); printArray(arr);

@ -10,11 +10,17 @@ public class Code03_NQueens {
return process1(0, record, n); return process1(0, record, n);
} }
// 当前来到i行一共是0~N-1行
// 在i行上放皇后所有列都尝试
// 必须要保证跟之前所有的皇后不打架
// int[] record record[x] = y 之前的第x行的皇后放在了y列上
// 返回不关心i以上发生了什么i.... 后续有多少合法的方法数
public static int process1(int i, int[] record, int n) { public static int process1(int i, int[] record, int n) {
if (i == n) { if (i == n) {
return 1; return 1;
} }
int res = 0; int res = 0;
// i行的皇后放哪一列呢j列
for (int j = 0; j < n; j++) { for (int j = 0; j < n; j++) {
if (isValid(record, i, j)) { if (isValid(record, i, j)) {
record[i] = j; record[i] = j;
@ -25,6 +31,7 @@ public class Code03_NQueens {
} }
public static boolean isValid(int[] record, int i, int j) { public static boolean isValid(int[] record, int i, int j) {
// 0..i-1
for (int k = 0; k < i; k++) { for (int k = 0; k < i; k++) {
if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) { if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) {
return false; return false;
@ -43,30 +50,30 @@ public class Code03_NQueens {
return process2(limit, 0, 0, 0); return process2(limit, 0, 0, 0);
} }
public static int process2( // 7皇后问题
int limit, // limit : 0....0 1 1 1 1 1 1 1
int colLim, // 之前皇后的列影响colLim
int leftDiaLim, // 之前皇后的左下对角线影响leftDiaLim
int rightDiaLim) { // 之前皇后的右下对角线影响rightDiaLim
public static int process2(int limit, int colLim, int leftDiaLim, int rightDiaLim) {
if (colLim == limit) { if (colLim == limit) {
return 1; return 1;
} }
int pos = limit & ( ~(colLim | leftDiaLim | rightDiaLim) ); // pos中所有是1的位置是你可以去尝试皇后的位置
int pos = limit & (~(colLim | leftDiaLim | rightDiaLim));
int mostRightOne = 0; int mostRightOne = 0;
int res = 0; int res = 0;
while (pos != 0) { while (pos != 0) {
mostRightOne = pos & (~pos + 1); mostRightOne = pos & (~pos + 1);
pos = pos - mostRightOne; pos = pos - mostRightOne;
res += process2(limit, res += process2(limit, colLim | mostRightOne, (leftDiaLim | mostRightOne) << 1,
colLim | mostRightOne,
(leftDiaLim | mostRightOne) << 1,
(rightDiaLim | mostRightOne) >>> 1); (rightDiaLim | mostRightOne) >>> 1);
} }
return res; return res;
} }
public static void main(String[] args) { public static void main(String[] args) {
int n = 14; int n = 15;
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
System.out.println(num2(n)); System.out.println(num2(n));

Loading…
Cancel
Save