計算機解決數獨,只是網上存個檔,勿噴
解決各類數獨 9x9 16x16
16x16的須要大量時間。
初始 0 表示 空
代碼
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
/**
* 數獨
*
* @author zlb
*/
public class ShuDu {
private final int DD_SIZE;
private final int SQRT_SIZE;
private final int[][] dd;
public ShuDu(String filePath) {
this(filePath, 9);
}
public ShuDu(String filePath, int size) {
DD_SIZE = size;
SQRT_SIZE = (int) Math.sqrt(size);
dd = new int[DD_SIZE][DD_SIZE];
if (SQRT_SIZE * SQRT_SIZE != DD_SIZE) {
throw new IllegalArgumentException(" size error !" + size);
}
BufferedReader in = null;
int vv = 0;
int i = 0;
try {
in = new BufferedReader(new FileReader(filePath));
String line;
for (i = 0; i < DD_SIZE; i++) {
while (null != (line = in.readLine())) {
line = line.trim();
if (!line.isEmpty()) {
break;
}
}
if(null !=line){
line = line.replaceAll("\\s{2,}", " ");
String[] cc = line.split(" ");
for (int j = 0; j < cc.length; j++) {
vv = Integer.valueOf(cc[j]);
dd[i][j] = vv;
}
}
}
} catch (Exception e) {
throw new IllegalArgumentException("參數異常 :filePath= " + filePath
+ " : " + i, e);
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
}
}
}
}
public int[][] getDd() {
return dd;
}
public void show(int[][] values) {
System.out.println("------------------------------------");
for (int i = 0; i < values.length; i++) {
for (int j = 0; j < values[i].length; j++) {
System.out.print(String.format("%-4d", values[i][j]));
}
System.out.println();
}
System.out.println("\n====================================");
}
public boolean isFormDD(int[][] values) {
for (int i = 0; i < DD_SIZE; i++) {
for (int j = 0; j < DD_SIZE; j++) {
if (0 != dd[i][j] && dd[i][j] != values[i][j]) {
return false;
}
}
}
return true;
}
public int check(int[][] values) {
int result = 0;
for (int i = 0; i < DD_SIZE; i++) {// 初始化
for (int j = 0; j < DD_SIZE; j++) {
if (0 != dd[i][j] && dd[i][j] != values[i][j]) {
result += 1;
continue;
}
if (check(values, i, j) > 0) {
result++;
}
}
}
return result;
}
protected int check(int[][] values, int row, int col) {
if (0 == values[row][col]) {
return 1;
}
int vv = values[row][col];
int j = row / SQRT_SIZE * SQRT_SIZE;
int k = col / SQRT_SIZE * SQRT_SIZE;
for (int i = 0; i < DD_SIZE; i++) {// check row
if (i != row && 0 == values[i][col] && vv == values[i][col]) {
return 2;
}
if (i != col && 0 == values[row][i] && vv == values[row][i]) {
return 3;
}
if (row != (j + i / SQRT_SIZE) && col != (k + i % SQRT_SIZE)) {
if (0 != values[j + i / SQRT_SIZE][k + i % SQRT_SIZE]
&& vv == values[j + i / SQRT_SIZE][k + i % SQRT_SIZE]) {
return 4;
}
}
}
return 0;
}
public int[][] exhaustiveAttack() {
int[][] tmp = new int[DD_SIZE][DD_SIZE];
for (int i = 0; i < DD_SIZE; i++) {// 初始化
for (int j = 0; j < DD_SIZE; j++) {
tmp[i][j] = dd[i][j];
}
}
if (solve(tmp, 0, 0)) {
System.out.println("solve & isFormDD == " + isFormDD(tmp));
}
return tmp;
}
protected AtomicLong callTime = new AtomicLong();
protected boolean solve(int[][] sk, int row, int col) {
long tmp = callTime.incrementAndGet();
if (tmp % 10000000 == 0) {
System.out.println(String
.format("%s do [%2s - %2s]", tmp, row, col));
}
if (col >= DD_SIZE) {
col = 0;
row++;
}
if (row >= DD_SIZE)
return true;
if (sk[row][col] != 0)
return solve(sk, row, ++col); // 若當前格子已有解則進行下一個格子的運算.
int sqrt_row = row / SQRT_SIZE * SQRT_SIZE;
int sqrt_col = col / SQRT_SIZE * SQRT_SIZE;
for (int i = 0; i < DD_SIZE; i++) {
int vv = i + 1;
for (int j = 0; j < DD_SIZE; j++) { // 非當前節點不在行列及宮中
if (row != j && sk[j][col] == vv) {
vv = 0;
break;
}
if (col != j && sk[row][j] == vv) {
vv = 0;
break;
}
if ((row != (sqrt_row + j / SQRT_SIZE) && col != (sqrt_col + j
% SQRT_SIZE))
&& vv == sk[sqrt_row + j / SQRT_SIZE][sqrt_col + j
% SQRT_SIZE]) {
vv = 0;
break;
}
}
sk[row][col] = vv;
if (vv > 0 && solve(sk, row, col + 1)) {
return true;
}
}
sk[row][col] = 0;
return false;
}
public static void main(String[] args) {
new ShuDu("./sd/jn1.txt").report();
}
public void report() {
show(dd);
System.out.println("is null : " + check(dd));
long time = System.currentTimeMillis();
int[][] result = exhaustiveAttack();
show(result);
time = System.currentTimeMillis() - time;
String msg = String.format("ok[ %s ] time[ %s ms ] call[ %s ]",
check(result), time, callTime.get());
System.out.println(msg);
}
}
示例輸入 9*9
9 0 6 0 1 3 0 0 8
0 5 8 0 0 0 0 9 0
0 3 0 0 0 0 0 1 0
0 6 0 8 0 0 9 2 0
0 0 3 4 0 9 1 0 0
0 4 9 0 0 6 0 3 0
0 9 0 0 0 0 0 8 0
0 1 0 0 0 0 6 7 0
4 0 0 9 6 0 3 0 1
示例 16*16
1 0 0 0 11 7 0 0 0 0 13 2 0 0 0 10
0 0 0 12 4 0 0 8 10 0 0 3 5 0 0 0
0 0 5 4 0 0 16 0 0 9 0 0 6 3 0 0
0 16 14 0 0 10 0 13 1 0 11 0 0 15 2 0
7 15 0 0 8 0 0 0 0 0 0 12 0 0 16 1
14 0 0 3 0 0 0 0 0 0 0 0 4 0 0 9
0 0 13 0 0 0 1 2 3 4 0 0 0 6 0 0
0 1 0 11 0 0 5 6 7 8 0 0 12 0 13 0
0 2 0 6 0 0 9 10 11 12 0 0 16 0 5 0
0 0 1 0 0 0 13 14 15 16 0 0 0 9 0 0
11 0 0 13 0 0 0 0 0 0 0 0 10 0 0 4
12 14 0 0 1 0 0 0 0 0 0 7 0 0 15 3
0 6 16 0 0 12 0 15 13 0 4 0 0 11 10 0
0 0 4 9 0 0 11 0 0 7 0 0 14 5 0 0
0 0 0 5 14 0 0 4 16 0 0 6 7 0 0 0
13 0 0 0 10 3 0 0 0 0 12 14 0 0 0 15