Java解数独效率提升方法
参考:深度搜索(递归)
虽说Java的运算速度确实快,但追求算法和提速是永恒的主题。
不满来自以下情况:
0 0 0 0 0 2 0 5 0
0 7 8 0 0 0 3 0 0
0 0 0 0 0 4 0 0 0
5 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0
0 0 0 0 3 0 7 0 8
2 0 0 0 0 0 0 4 0
0 0 0 0 0 5 0 9 0
0 1 0 0 7 0 0 0 0
3 9 6 7 1 2 8 5 4
4 7 8 6 5 9 3 1 2
1 5 2 3 8 4 9 7 6
5 8 1 2 6 7 4 3 9
7 2 3 9 4 8 1 6 5
6 4 9 5 3 1 7 2 8
2 6 7 8 9 3 5 4 1
8 3 4 1 2 5 6 9 7
9 1 5 4 7 6 2 8 3
程序运行时间:5.2010000000000005s
程序修订后,上述数独的破解从原来的5秒左右,提升到0.041秒,是一个巨大的进步。
修订思路:
1、对数独中的0的个数进行统计,在此基础上对可填数字的数量进行统计。
2、优先处理当前可填数字最少的那个0,优化深度搜索策略。
package good;
import java.util.Scanner;
public class sd {
static int[][] arr1={{8, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 3, 6, 0, 0, 0, 0, 0},
{0, 7, 0, 0, 9, 0, 2, 0, 0},
{0, 5, 0, 0, 0, 7, 0, 0, 0},
{0, 0, 0, 0, 4, 5, 7, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 3, 0},
{0, 0, 1, 0, 0, 0, 0, 6, 8},
{0, 0, 8, 5, 0, 0, 0, 1, 0},
{0, 9, 0, 0, 0, 0, 4, 0, 0}};
static int[][] arr2={{0, 0, 0, 0, 0, 2, 0, 5, 0},
{0, 7, 8, 0, 0, 0, 3, 0, 0},
{0, 0, 0, 0, 0, 4, 0, 0, 0},
{5, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 3, 0, 7, 0, 8},
{2, 0, 0, 0, 0, 0, 0, 4, 0},
{0, 0, 0, 0, 0, 5, 0, 9, 0},
{0, 1, 0, 0, 7, 0, 0, 0, 0}};
static int[][] arr3={{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 6, 0, 3, 0, 4, 0, 2, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 5},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 6, 8, 0, 3, 0, 0},
{1, 0, 5, 0, 7, 0, 0, 0, 0},
{0, 0, 0, 0, 5, 0, 0, 0, 0},
{0, 3, 0, 0, 0, 0, 4, 0, 0},
{8, 0, 0, 9, 0, 0, 0, 0, 0}};
static int[][] arr4={{0, 0, 5, 3, 0, 0, 0, 0, 0},
{8, 0, 0, 0, 0, 0, 0, 2, 0},
{0, 7, 0, 0, 1, 0, 5, 0, 0},
{4, 0, 0, 0, 0, 5, 3, 0, 0},
{0, 1, 0, 0, 7, 0, 0, 0, 6},
{0, 0, 3, 2, 0, 0, 0, 8, 0},
{0, 6, 0, 5, 0, 0, 0, 0, 9},
{0, 0, 4, 0, 0, 0, 0, 3, 0},
{0, 0, 0, 0, 0, 9, 7, 0, 0}};
static int[][] arr5={{0, 8, 0, 0, 0, 0, 0, 0, 0},
{9, 0, 0, 5, 0, 0, 7, 0, 0},
{0, 0, 1, 0, 0, 4, 0, 0, 2},
{8, 0, 0, 0, 0, 1, 2, 0, 4},
{0, 0, 0, 0, 9, 0, 0, 0, 0},
{0, 5, 3, 7, 0, 0, 0, 9, 0},
{0, 6, 0, 0, 0, 2, 0, 8, 0},
{0, 0, 2, 1, 0, 0, 0, 0, 7},
{0, 0, 0, 0, 0, 0, 6, 0, 0}};
static int[][] arr6={{9, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 3, 6, 0, 0, 0, 0, 0},
{0, 7, 0, 0, 9, 0, 2, 0, 0},
{0, 5, 0, 0, 0, 7, 0, 0, 0},
{0, 0, 0, 0, 4, 5, 7, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 3, 0},
{0, 0, 1, 0, 0, 0, 0, 6, 8},
{0, 0, 8, 5, 0, 0, 0, 1, 0},
{0, 9, 0, 0, 0, 0, 4, 0, 0}};
static int[][] arr=new int[9][9];
static int count=0;
static long startTime;
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("请选择数独库,输入数字1-6:");
Scanner x = new Scanner(System.in);
int n = x.nextInt();
startTime = System.currentTimeMillis();
switch(n) {
case 1:
arr=arr1;break;
case 2:
arr=arr2;break;
case 3:
arr=arr3;break;
case 4:
arr=arr4;break;
case 5:
arr=arr5;break;
case 6:
arr=arr6;
}
show();
for(int i=0;i<=80;i+=1) {
if(arr[i/9][i%9]==0) {
count+=1;
}
}
dfs(0);
System.out.println("无解!");
}
public static boolean logic(int y, int x, int k) {
for(int i=0;i<9;i+=1) {
if(k==arr[y][i]) {
return false;
}
}
for(int j=0;j<9;j+=1) {
if(k==arr[j][x]) {
return false;
}
}
int h=(y / 3) * 3 * 9 + (x / 3) * 3;
for(int head=h;head<=h+18;head+=9) {
for(int j=head;j<head+3;j+=1) {
if(k==arr[j/9][j%9]){
return false;
}
}
}
return true;
}
public static void show() {
for(int i=0;i<9;i+=1) {
for(int j=0;j<9;j+=1) {
System.out.print(arr[i][j]+" ");
}
System.out.println("");
}
System.out.println("");
if(count>0) {
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间:" + (endTime - startTime)*0.001 + "s");
System.exit(0);
}
}
public static int getvip() {
int minn=10;
int indexx=0;
for(int i=0;i<=80;i+=1) {
if(arr[i/9][i%9]==0) {
int c=0;
for(int av=1;av<=9;av+=1) {
if(logic(i/9,i%9,av)) {
c+=1;
}
}
if(minn>c) {
minn=c;
indexx=i;
if(minn==1) {
return indexx;
}
if(minn==0) {
return -1;
}
}
}
}
return indexx;
}
public static void dfs(int n) {
int m=getvip();
if(m==-1) {
return;
}
//System.out.println(vector1.size());
for(int avail=0;avail<=9;avail+=1) {
if(logic(m/9,m%9,avail)) {
arr[m/9][m%9]=avail;
if(n==count-1) {
show();
}
dfs(n + 1);
arr[m/9][m%9]=0;
}
}
}
}
请选择数独库,输入数字1-6:
2
0 0 0 0 0 2 0 5 0
0 7 8 0 0 0 3 0 0
0 0 0 0 0 4 0 0 0
5 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0
0 0 0 0 3 0 7 0 8
2 0 0 0 0 0 0 4 0
0 0 0 0 0 5 0 9 0
0 1 0 0 7 0 0 0 0
3 9 6 7 1 2 8 5 4
4 7 8 6 5 9 3 1 2
1 5 2 3 8 4 9 7 6
5 8 1 2 6 7 4 3 9
7 2 3 9 4 8 1 6 5
6 4 9 5 3 1 7 2 8
2 6 7 8 9 3 5 4 1
8 3 4 1 2 5 6 9 7
9 1 5 4 7 6 2 8 3
程序运行时间:0.041s