zoukankan      html  css  js  c++  java
  • sudoku solver(数独)

    Write a program to solve a Sudoku puzzle by filling the empty cells.

    Empty cells are indicated by the character '.'.

    You may assume that there will be only one unique solution.

    A sudoku puzzle...

    1 每个backtracking的题目,最好都有独立判断isValid的程序,这样架构清楚。同时,valid判断函数在这里可以稍微研究一下。只要当前要判断的位置上的数值和本行没有重复,本列没有重复,九宫格没有重复就可以。一旦重复立即返回,减少判断次数。

    2 backtracking的递归函数,怎么能没有返回值呢?!因为要判断递归的方案正确与否,所以这里的递归一定是有返回值的(除非是combination那种没有正确错误概念的backtracking)!

    3 可以考虑“先放置,再判断”的方案。比如这里,首先判断当前位置是否为空,如果为空,那么放置一个元素,检查它是否正确。如果正确,就继续进行下面的递归(也就是第29行 isValid&&solveSudoku的作用)。当函数返回错误之后,将刚刚的数值变为空,再进行下一次尝试即可。

    5 最后一点需要注意的是,当i,j循环完毕之后,表明已经解出了sudoku,需要返回!切记切记,最终情况!

    简单地说思路就是循环处理子问题,对于每个格子,带入不同的9个数,然后判合法,如果成立就递归继续,结束后把数字设回空。大家可以看出代码结构和N-Queens是完全一样的。判合法其实在这里因为每次进入时已经保证之前的board不会冲突,所以不需要判断整个盘,只需要看当前加入的数字和之前是否冲突就可以,这样可以大大提高运行效率,毕竟判合法在程序中被多次调用。

    class Solution {
        public void solveSudoku(char[][] board) {
            helper(board,0,0);
        }
        //判断row,col位置是否为'.',是的话就设置值。
        //因为要判断是否正确,所以需要返回值
        public boolean helper(char[][] board,int row,int col){
            if(col>=9){  //下一个位置超出列,就是进行下一行
               return helper(board,row+1,0);
            }
            if(row==9){
                return true;
            }
            //如果该位置是'.',则要添加数字
            if(board[row][col]=='.'){
                //依次给该位置添加1-9
                for(int k=1;k<=9;k++){
                    board[row][col]=(char)(k+'0');
                    if(isValid(board,row,col)){//如果有效,就进行下一个位置添加
                        if(helper(board,row,col+1))//如果后面的添加返回true,表明添加成功,返回true,否则就尝试下一个k
                            return true;
                    }
                    board[row][col]='.';
                }
            }else{
               return helper(board,row,col+1);
            }
            return false;
        }
        /*
        前面都已经判断了,只要判断该位置添加数字后是否符合要求,也就是看该行、列有没有和该元素相同的,而且该位置所在的九宫格中也不能有和它相同的
        */
        public boolean isValid(char[][] board,int row,int col){
            //判断列是否有相同的,再同列不同行,元素却相同
            for(int i=0;i<9;i++){
                if(i!=row&&board[i][col]==board[row][col]) 
                    return false;
            }
            //判断行是否有相同的,同行不同列
            for(int j=0;j<9;j++){
                if(j!=col&&board[row][col]==board[row][j])
                    return false;
            }
            
            //判断该位置所在九宫格是否有相同的
            /*要根据该位置找到所在九宫格的行和列的范围
            每个九宫格的行的范围是0-2,3-5,6-8,
            */
            for(int i=row/3*3;i<row/3*3+3;i++)
            {
                for(int j=col/3*3;j<col/3*3+3;j++){
                    if((i!=row||j!=col)&&board[i][j]==board[row][col])
                        return false;
                }
            }
            
            return true;
        }
    }
  • 相关阅读:
    DAY12 基本余数 运算符2
    DAY11 基本运算符
    DAY10 变量 常量 作用域
    DAY09 JAVA 类型转换
    DAY08 数据类型2
    DAY07 数据类型
    DAY06 JAVA基础语法1注释2标识符
    Beta冲刺集合
    Alpha冲刺集合
    高级软件工程实践总结
  • 原文地址:https://www.cnblogs.com/xiaolovewei/p/8320182.html
Copyright © 2011-2022 走看看