POJ - 2676 Sudoku

                                                     Sudoku

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

做题思路:

        明白数独规则之后,应该要想到用深搜模拟填数字,搜索所有填入可能之后找到合适的一组输出。需要注意的就是说9*9的大九宫格内还有九个小的3*3的小九宫格,每个都要满足数独的要求。此代码用了三个辅助数组,a数组记录需要填数字的数独坐标,并且记录有几个待填的数字。hang数组记录此行有没有该数字,lie数组记录该列有没有该数字。还有一个判断函数yun,用来判断小九宫格内有没有出现该数字。还有代码中需要注意的是行列数是0~8,而数字是1~9,所以代码当中有一部分将两者合并起来利用,需要注意。具体思路及注意看代码中注释。

代码:

      

#include<stdio.h>
#include<string.h>

int map[10][10];              //map数组记录整型数组状态
int a[85][2], hang[10][10], lie[10][10];  //数组a,b,c作用见主函数内注释

int yun(int i, int j, int k)     //检查一个小九宫格内是否有重复数字
{
    int p, q;
    for( p = i/3*3; p <= i/3*3+2; p++)
        for( q = j/3*3; q <= j/3*3+2; q++ )
            if( map[p][q] == k )
                return 0;
    return 1;
}

int dfs(int w)
{
    int i, j, k;
    j = a[w][0], k = a[w][1];
    if( w < 0 ) return 1;  //可填入数字个数为0时即整个数独填写完毕
    for( i = 0; i < 9; i++ ) //尝试填入数字1~9,看是否合适
    {
        if( yun(j,k,i+1) && !hang[j][i] && !lie[k][i] )//
        {
            //如果该数字在小宫格内合适,并且该行和该列也没有此数字,则可以暂时填入此数字
            hang[j][i] = lie[k][i] = 1;   //此行此列标记为已经出现过该数字
            map[j][k] = i+1;         //填入数字
            if( dfs(w-1) ) return 1;
            hang[j][i] = lie[k][i] = 0;   //取消标记
            map[j][k] = 0;           //取消数字填入
        }
    }
    return 0;
}

int main()
{
    int T, w;
    char s[10];
    scanf("%d",&T);
    while( T-- )
    {
        memset( hang,0,sizeof(hang) );
        memset( lie,0,sizeof(lie) );
        w = 0;
        for( int i = 0; i < 9; i++ )     //输入数独
        {
            scanf("%s",s);               //以字符串形式输入
            for( int j = 0; j < 9; j++ )
            {
                map[i][j] = s[j] - '0';  //转化为整型(即数字)
                if( !map[i][j] )         //如果该数字为0
                {
                    a[w][0] = i;         //记录可以填入数字的坐标
                    a[w][1] = j;
                    w++;                 //w用来记录可填入数字的个数
                }
                if( map[i][j] )    //如果该数字不为0则记录该行该列已经出现此数字
                {
                    hang[i][map[i][j]-1] = 1;
                    lie[j][map[i][j]-1] = 1;
                }
            }
        }
        dfs( w-1 );
        for( int i = 0; i < 9; i++ )
        {
            for( int j = 0; j < 9; j++ )
                printf("%d",map[i][j]);
            printf("\n");
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值