zoukankan      html  css  js  c++  java
  • 算法:求解Sukodu数独

    题目描述

    问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个粗线宫内的数字均含1-9,并且不重复。
    输入:
    包含已知数字的9X9盘面数组[空缺位以数字0表示]
    输出:
    完整的9X9盘面数组

    思路

    这题在leetcode上见过,当时没有去解。直观上感受题目,最先想到的还是暴力遍历每种情况,但害怕时间复杂度会特别的高,所以迟迟不敢下手,今天实在是想不到了,就看了下别人的想法,发现还是深度遍历各种情况,草。

    代码

    import java.util.HashSet;
    import java.util.Scanner;
    import java.util.Set;
    
    public class Main {
        private static int[][] m;
        public static void main(String...a){
            Scanner in = new Scanner(System.in);
            while (in.hasNext()) {
                m = new int[9][9];
                for (int i = 0; i < 9; i++) {
                    for (int j = 0; j < 9; j++) {
                        m[i][j] = in.nextInt();
                    }
                }
    
                helper(0, 0);
    
                for (int i = 0; i < 9; i++) {
                    for (int j = 0; j < 9; j++) {
                        System.out.print(m[i][j]);
                        if (j < 8) System.out.print(' ');
                    }
                    System.out.println();
                }
            }
        }
        private static Boolean helper(int x, int y){
        /*
            从二维数组的m[0][0]开始扫描第一行,当扫描到行尾时,转入扫描下一行。
            扫描过的位置代表里边的数字符合规则,若能扫描到完最后一行,那么说明整个数独填补完了
            当扫描到一个空位时,开始尝试填入数字,当所数字1-9都不能填补这个位置时,说明前面某个填的位置出现错误
        */
            if (x >= 9) return true;
            if (y >= 9) return helper(x+1, 0);
            if (m[x][y] != 0) return helper(x, y + 1);
    
            Set<Integer> existsNum = getExistsNum(x, y);
            for (int i = 1; i <= 9; i++) {
                if (existsNum.contains(i)) continue;
                m[x][y] = i;
                if (helper(x, y + 1)) {
                    return true;
                }
                m[x][y] = 0;
            }
            return false;
        }
        private static Set<Integer> getExistsNum(int x, int y){
            Set<Integer> set = new HashSet<>();
            for (int i = 0; i < 9; i++) {//查看行和列出现过的数字
                if (m[x][i] != 0) {
                    set.add(m[x][i]);
                }
                if (m[i][y] != 0) {
                    set.add(m[i][y]);
                }
            }
            int startX = x / 3 * 3, startY = y / 3 * 3;
            for (int i = 0; i < 3; i++) {//查看九宫格中出现过的数字
                for (int j = 0; j < 3; j++) {
                    if (m[startX + i][startY + j] != 0) {
                        set.add(m[startX + i][startY + j]);
                    }
                }
            }
            return set;
        }
    }
           
  • 相关阅读:
    从csv文件里取数据作为请求参数,和把返回数据放到一个csv文件
    记一次if控制器的使用
    记一次使用正则表达式+foreach控制器调试
    获取随机数用作入参使用
    获取返回结果作为参数并将其设置为全局变量(实现跨线程组使用)
    linux默认的目录结构
    总结fiddler抓https包
    Codeforces Round #733 (Div. 1 + Div. 2) D. Secret Santa
    Codeforces Round #733 (Div. 1 + Div. 2) C. Pursuit
    Codeforces Round #731 (Div. 3) A
  • 原文地址:https://www.cnblogs.com/liuyongyu/p/13546998.html
Copyright © 2011-2022 走看看