50,503
社区成员
发帖
与我相关
我的任务
分享
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class Main {
private int width, height;
private int[][] array;
private Point[] point;
private int[][] result;
private Map<Key, Long> cache = new HashMap<Key, Long>();
/* 跳的方向
* 6 1
* 5 0 2
* 4 3
*/
private int[][] direction = {{1, -1}, {2, 0}, {1, 1}, {-1, 1}, {-2, 0}, {-1, -1}};
private static class Point {
public int x, y, value;
public Point(int x, int y, int value) {
this.x = x;
this.y = y;
this.value = value;
}
}
private static class Key {
public int[][] point;
@Override
public int hashCode() {
int hash = 5;
hash = 23 * hash + Arrays.deepHashCode(this.point);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Key other = (Key) obj;
if (!Arrays.deepEquals(this.point, other.point)) {
return false;
}
return true;
}
}
public Main(int n) {
int maxValue = (1 + n) * n / 2 - 1;
width = n * 2 - 1;
height = n;
array = new int[height][width];
point = new Point[maxValue];
result = new int[maxValue][2];
int k = 0;
for (int y = 0; y < n; y++) {
Arrays.fill(array[y], -1);
int s = n - y - 1;
for (int i = 0; i <= 2 * y; i++) {
if (i % 2 != 0) {
array[y][s + i] = 0;
continue;
}
if (k == 0) {
array[y][s + i] = 0;
} else {
array[y][s + i] = k;
point[k - 1] = new Point(s + i, y, k);
}
k++;
}
}
printArray();
}
private void printArray() {
for (int y = 0; y < height; y++) {
for (int i = 0; i < array[y].length; i++) {
System.out.format("%2d ", array[y][i]);
}
System.out.println();
}
}
public long g() {
return g(point.length);
}
/**
* 此时棋盘的形态(依次记录有棋子的格子的坐标)
* @param n
* @return
*/
private Key buildKey(int n) {
Key key = new Key();
key.point = new int[n][2];
int k = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] > 0) {
key.point[k++] = new int[]{i, j};
}
}
}
return key;
}
private long g(int n) {
if (n == 1) {
for (int i = result.length; i > 1; i--) {
System.out.format("%2d->%2d ", result[i - 1][0], result[i - 1][1]);
}
System.out.println("");
return 1;
}
/* 不使用缓存 */
// if (1 > 0) {
// return g2(n);
// }
Key key = buildKey(n);
Long total = cache.get(key);
if (total != null) {
//System.out.println("hit:" + total);
return total;
}
long s = g2(n);
cache.put(key, s);
return s;
}
/**
* 此时,棋盘是否对称
* @return
*/
private boolean isSymmetrical() {
int center = width / 2;
for (int y = 0; y < array.length; y++) {
for (int i = 1; i <= y; i++) {
int k = 0;
k += (array[y][center + i] == 0 ? 0 : 1);
k += (array[y][center - i] == 0 ? 0 : -1);
if (k != 0) {
return false;
}
}
}
return true;
}
private long g2(int n) {
long s = 0;
/* 此时,棋盘是否对称的*/
// boolean symmetrical = false;
boolean symmetrical = isSymmetrical();
for (int i = 0; i < point.length; i++) {
Point p = point[i];
if (p == null) {
continue;
}
int offset = p.x - width / 2;
//对称的时候,右边的棋子不用计算
if (symmetrical && offset > 0) {
continue;
}
for (int j = 0; j < direction.length; j++) {
int x0 = p.x, x1 = p.x + direction[j][0], x2 = p.x + direction[j][0] * 2;
int y0 = p.y, y1 = p.y + direction[j][1], y2 = p.y + direction[j][1] * 2;
if (x2 < 0 || x2 >= width || y2 < 0 || y2 >= height
|| array[y1][x1] == 0 || array[y2][x2] != 0) {
continue;
}
//对称的时候,中间的棋子往右跳不用计算
if (symmetrical && offset == 0 && direction[j][0] > 0) {
continue;
}
result[n - 1][0] = array[y0][x0];
result[n - 1][1] = array[y1][x1];
array[y2][x2] = array[y0][x0];
p.x = x2;
p.y = y2;
array[y0][x0] = 0;
//
Point destroyed = point[array[y1][x1] - 1];
point[array[y1][x1] - 1] = null;
array[y1][x1] = 0;
//
s += g(n - 1);
//
array[y1][x1] = destroyed.value;
point[array[y1][x1] - 1] = destroyed;
//
array[y0][x0] = p.value;
p.x = x0;
p.y = y0;
array[y2][x2] = 0;
}
}
return symmetrical ? s * 2 : s;
}
public static void main(String[] args) throws Exception {
long a = System.nanoTime();
Main m = new Main(6);
long total = m.g();
System.out.println("total:" + total);
long b = System.nanoTime();
System.out.println("spend:" + TimeUnit.NANOSECONDS.toSeconds(b - a) + "s");
}
}