回溯法数独求解

public class SoduTest {
private int[][] sodu = {
// 最难的
// {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}

        // 包含两个解的
        {7,6,1,2,4,5,8,3,9},
        {3,2,8,1,7,9,4,5,6},
        {0,0,4,8,3,6,7,2,1},
        {8,7,5,9,6,4,2,1,3},
        {2,3,9,7,5,1,6,4,8},
        {1,4,6,2,8,3,9,7,5},
        {4,1,7,3,9,8,5,6,2},
        {0,0,3,4,2,6,1,8,7},
        {6,8,2,5,1,7,3,9,4}
};
public static void main(String[] args) {
    long timeStart = System.currentTimeMillis();
    new SoduTest().getSoduAnswer(0, 0);
    long timeStop = System.currentTimeMillis();
    System.out.println("It took " + (timeStop - timeStart) + " milliseconds");
}

/**
 * 核心算法,利用递归回溯,求出所有解
 * @param x 起始第 x 行
 * @param y 起始第 y 列
 * @return
 */
private boolean getSoduAnswer(int x, int y) {
    if(y == 9) {
        // 终止条件
        if(x == 8) {
            // 打印
            printSodu(this.sodu);
            System.out.println("-------------------------------------------");
            // 若返回true,则求出一个解后退出

// return true;
// 若返回false,则求出一个解后向前回溯,直到求出所有解
return false;
}
// 换行
x++;
y = 0;
}
// 如果不为0,直接计算下一个数
if(this.sodu[x][y] != 0) {
return getSoduAnswer(x, y+1);
}
// 尝试 1-9 是否满足条件
for(int i = 1; i <= 9; i++) {
if(this.checkSoduNum(x, y, i)) {
//满足条件设置值
this.sodu[x][y] = i;
//并尝试下一个数是否满足条件
if(getSoduAnswer(x, y+1)) {
return true;
}else {
// 若不满足条件,进行回溯
this.sodu[x][y] = 0;
}
}
}
return false;
}

/**
 * 判断值是否合理
 * @param x
 * @param y
 * @param soduNum
 * @return
 */
private boolean checkSoduNum(int x, int y, int soduNum) {
    // 判断当前行,列是否有重复
    for(int i = 0;i < 9;i++) {
        if(this.sodu[x][i] == soduNum) {
            return false;
        }
        if(this.sodu[i][y] == soduNum) {
            return false;
        }
    }
    // 求出左上角坐标
    int a = x - (x % 3);
    int aStop = a+3;
    int b = y - (y % 3);
    int bStop = b+3;
    // 判断当前方框内是否有重复
    for(a = x - (x % 3);a<aStop;a++) {
        for(b = y - (y % 3);b<bStop;b++) {
            if(this.sodu[a][b] == soduNum) {
                return false;
            }
        }
    }
    return true;
}

/**
 * 打印数组
 * @param sodu
 */
public static void printSodu(int[][] sodu) {
    for(int i = 0; i < sodu.length; i++) {
        int[] soduX = sodu[i];
        for(int j = 0; j < soduX.length; j++) {
            int soduY = soduX[j];
            if(j != 0 && j % 3 == 0) {
                System.out.print(" ");
            }
            System.out.print(soduY);
        }
        System.out.println();
        if(i != 0 && (i+1) % 3 == 0) {
            System.out.println();
        }
    }
}

}

原文:https://www.cnblogs.com/gode/archive/2019/06/17/11039367.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值