分治回溯---数独

数独

如图,一个9*9的方阵,格子中可以填1-9,每一行不能有相同的数字,每一列也不能有相同的数字,同时每一个小的九宫格也不能有相同的数字
在这里插入图片描述

像上图这样我们可以表示成

5 3 0 0 7 0 0 0 0 
6 0 0 1 9 5 0 0 0 
0 9 8 0 0 0 0 6 0 
8 0 0 0 6 0 0 0 3 
4 0 0 8 0 3 0 0 1 
7 0 0 0 2 0 0 0 6 
0 6 0 0 0 0 2 8 0 
0 0 0 4 1 9 0 0 5 
0 0 0 0 8 0 0 7 9 

需要填数字格子可以用0去表示
在编写代码前,我们需要去解决几个问题
9*9的方格我们将他们存储在一个二维数组中
其中行列的范围都是0-8

在进行解决问题时,我们第一步需要去判断改格子是否为0,是的话再进行填字,不是的话我们需要对下一个格子进行判断

如果是0,我们则对改格子进行赋值,从1-9依次去赋值,判断可以不,可以的话进行下一个格子判断,如果下一个格子将1-9都填了一遍都不行,那么就会回退到上一个状态,并将当前格子进行清零,然后上一个状态再继续进行填格子

当对下一个格子进行判断时,如果下一个格子和当前格子是在同一行,那么行不变,列加一即可,但是如果当前格子在行的最后一个,那么下一个格子位置就是行加1,列置为0

row + (col + 1) / 9, (col + 1) % 9

判断九宫格内元素是否相同时
九宫格的行和列的范围是:0-2,3-5,6-8

int rowMin = (row / 3) * 3; // 4
int rowMax = rowMin + 2;

int colMin = (col / 3) * 3;
int colMax = colMin + 2;

package p4.分治回溯;

import java.io.*;
//数独
public class Sudoku {
    private static int i = 0;
    private static int[][] board = new int[9][9];

    public static void main(String[] args) throws IOException {
        readFile("sudoku_data_01.txt"); // 将文件中的数据读取存储在board中
        solve(0, 0);// 从0,0这个位置开始填数独,进行解题
    }

    //求解x-y格子的解 再继续向下递归求解下一个格子
    //本质求多个解 但实际 数独问题只能有一个解 如果没解 程序啥也不输出!
    private static void solve(int row, int col) {
        if (row == 9) { // 角标是0-8
            i++;
            System.out.println("===========" + i + "==========");
            printBoard();
            //System.exit(0);
        } else {
            if (board[row][col] == 0) {
                //需要填数字1~9
                for (int num = 1; num <= 9; num++) {
                    if (!isExist(row, col, num)) {
                        board[row][col] = num; //8
                        //解决下一个格子
                        solve(row + (col + 1) / 9, (col + 1) % 9);
                    }
                    //如果此处没解 必须清零
                    board[row][col] = 0;
                }
            } else {
                //已经存在一个已知数字 直接跳过去解决下一个格子
                solve(row + (col + 1) / 9, (col + 1) % 9);
            }
        }
    }

    private static boolean isExist(int row, int col, int num) {
        //同行
        for (int c = 0; c < 9; c++) {
            if (board[row][c] == num) {
                return true;
            }
        }

        //同列
        for (int r = 0; r < 9; r++) {
            if (board[r][col] == num) {
                return true;
            }
        }

        //同九宫 3*3
        int rowMin = (row / 3) * 3; // 4
        int rowMax = rowMin + 2;

        int colMin = (col / 3) * 3;
        int colMax = colMin + 2;

        for (int r = rowMin; r <= rowMax; r++) {
            for (int c = colMin; c <= colMax; c++) {
                if (board[r][c] == num) {
                    return true;
                }
            }
        }

        return false;
    }

    private static void readFile(String fileName) throws IOException {
        File file = new File(fileName);
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
        String line = null;
        int row = 0;
        while ((line = br.readLine()) != null) {
            for (int col = 0; col < 9; col++) {
                board[row][col] = Integer.parseInt(line.charAt(col) + "");
            }
            row++;
        }
    }

    private static void printBoard() {
        for (int i = 0 ; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                System.out.print(board[i][j] + " ");
            }
            System.out.println();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值