zoukankan      html  css  js  c++  java
  • POJ2676 – Sudoku(数独)—DFS

    Sudoku
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 24081   Accepted: 11242   Special Judge

    Description

    Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the cells are written decimal digits from 1 to 9. The other cells are empty. The goal is to fill the empty cells with decimal digits from 1 to 9, one digit per cell, in such way that in each row, in each column and in each marked 3x3 subsquare, all the digits from 1 to 9 to appear. Write a program to solve a given Sudoku-task. 

    Input

    The input data will start with the number of the test cases. For each test case, 9 lines follow, corresponding to the rows of the table. On each line a string of exactly 9 decimal digits is given, corresponding to the cells in this line. If a cell is empty it is represented by 0.

    Output

    For each test case your program should print the solution in the same format as the input data. The empty cells have to be filled according to the rules. If solutions is not unique, then the program may print any one of them.

    Sample Input

    1
    103000509
    002109400
    000704000
    300502006
    060000050
    700803004
    000401000
    009205800
    804000107

    Sample Output

    143628579
    572139468
    986754231
    391542786
    468917352
    725863914
    237481695
    619275843
    854396127

    题意:就是普通的数独游戏,给出了初始状态的九宫格,让你打印出任意一种解法。
    思路:这题用DFS来写。我们运用三个数组进行标记,从而得知每个格子可以放那些数,不可以放哪些数,然后dfs枚举即可。三个标记数组分别为line[][],column[][],block[][],
    line:标记每一行哪些数已经被用了,哪些没被用;
    column:标记每一列哪些数已经被用了,哪些没被用;
    block:标记每一个3*3格子中哪些数被用过,哪些没被用;(判断某个格子为第几个块:3*3的块总共有三行和三列,假设格子索引从1-9,某个格子为第i行,第j列,可以知道它是(i-1)/3行的块,而且是(j-1)/3+1列的列,所以可以知道某个格子为第(i-1)/3*3+(j-1)/3+1块)
    然后从第一个需要填数的格子开始,枚举1-9中可以填的所有数,然后将选中的数标记,继续下一个格子,若到达某个格子无数可选,则回溯。
    具体看代码,最近在学Java,所以代码是用java写的,但语法基本和C++相同,所以不会java也能看懂。

    代码:
     1 import java.util.Scanner;
     2 
     3 public class Main {
     4     static boolean line[][]; //标记行的数组,一维的数字表示第几行,二维的数字表示这一行的哪一个数
     5     static boolean column[][]; //标记列的数组
     6     static boolean block[][]; //标记块的数组
     7     
     8     public static void main(String[] args) {
     9         Scanner in = new Scanner(System.in);
    10         int t = in.nextInt(); //输入t
    11         while(t-- > 0) 
    12         {
    13             line = new boolean[15][15]; //数组初始化
    14             column = new boolean[15][15];
    15             block = new boolean[15][15];
    16             
    17             int map[][] = new int[15][15];
    18             int all = 0; //all用来统计有多少个格子需要填数
    19             for(int i=1; i<10; ++i) {
    20                 String s = in.next(); //输入字符串
    21                 
    22                 for(int j=1; j<10; ++j) {
    23                     map[i][j] = s.charAt(j-1) - '0'; //将字符串转化为数字存入数组
    24                     if(map[i][j] == 0) all++; //统计
    25                     
    26                     line[i][ map[i][j] ] = true; //标记每一个已经出现的数
    27                     column[j][ map[i][j] ] = true;
    28                     int xx = (i-1)/3*3 + (j-1)/3 + 1; //计算这个格子在第几个3*3的块中
    29                     block[xx][ map[i][j] ] = true;
    30                 }
    31             }
    32             
    33             outer:for(int i=1; i<10; ++i) //找到第一个需要填的格子
    34                 for(int j=1; j<10; ++j) {
    35                     if(map[i][j] == 0)
    36                     {
    37                         DFS(i,j,all,map);
    38                         break outer; //跳出到循环外
    39                     }
    40                 }
    41             
    42             for(int i=1; i<10; ++i)
    43             {
    44                 for(int j=1; j<10; ++j)
    45                 {
    46                     System.out.print(map[i][j]);
    47                 }
    48                 System.out.println();
    49             }
    50         }
    51         in.close();
    52     }
    53     
    54     static boolean DFS(int x,int y,int all,int[][] map) {
    55         
    56         if(all == 0) { //如果所有的格子都被填满,返回true
    57             return true;
    58         }
    59         
    60         int x1=0,y1=0;
    61         outer:for(int i=x; i<10; ++i) //找到这个格子之后需要填数的第一个格子
    62             for(int j=1; j<10; ++j)
    63             {
    64                 if(i==x && j==y) continue; //跳过目前这个格子
    65                 if(map[i][j] == 0)
    66                 {
    67                     x1 = i;
    68                     y1 = j;
    69                     break outer;
    70                 }
    71             }
    72         
    73         int xx = (x-1)/3*3 + (y-1)/3 + 1; //计算这个格子为第几个块
    74         for(int k=1; k<10; ++k) {
    75             if(!line[x][k] && !column[y][k] && !block[xx][k] ) //若这个数未被标记,表示可选
    76             {
    77                 map[x][y] = k; //在这个格子存储这个数
    78                 line[x][k] = true; //将这个数标记
    79                 column[y][k] = true;
    80                 block[xx][k] = true;
    81                 
    82                 if(DFS(x1,y1,all-1,map)) //搜索下一个需要填数的格子
    83                     return true;
    84                 
    85                 line[x][k] = false; //能运行到这里,说明填数失败,所以回溯
    86                 column[y][k] = false;
    87                 block[xx][k] = false;
    88             }
    89         }
    90         map[x][y] = 0; //若没有一个数满足要求,则回到上一个数,且要把这个数变回0;
    91         return false;
    92     }
    93 }
  • 相关阅读:
    mapr
    短信 流控规则
    js modify local file
    An O(ND) Difference Algorithm and Its Variations (1986)
    美团金融扫码付静态资源加载优化实践
    前端遇上Go: 静态资源增量更新的新实践
    小程序短信验证码登录的实现与优化
    A Practical Introduction to Blockchain with Python
    numpy计算
    小程序登录方式切换 不做url跳转
  • 原文地址:https://www.cnblogs.com/tuyang1129/p/9614177.html
Copyright © 2011-2022 走看看