暑假练习--hdoj--搜索--suduku

来源:互联网 发布:淘宝怎么设置客服认证 编辑:程序博客网 时间:2024/06/08 04:06

这个题必须要写一篇博客了……这个题算是做过的最久的一道题吧。想了很长时间,一直没想好怎么做。要保证每一行每一列还有没个格子都不重复,行和列还好说,每个格子不一样不知道怎么做。搜索的话,开始是想几个方向一起搜,但是想想不行,又想一行一列一起搜,想想也不行。想了好久都不知道怎么搜。实在想不出来了,最后了解了一下别人的思路,一行一行的搜……感觉也考虑过……但是就这个没写过了。

下面是原题:(感觉这个代码可以解决所有数独的问题,感觉像是完成了一项大工程一样……)

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
1103000509002109400000704000300502006060000050700803004000401000009205800804000107
 

Sample Output
143628579572139468986754231391542786468917352725863914237481695619275843854396127


这个题比较关键的地方就在于对数字的标记。即这个数存在过,就在数组中进行标记。对于格子的问题,也可以标记……

解题思路就是从最左上角开始,满足条件DFS(i,j+1),如果j == 8,搜下一行DFS(i+1,j)。一直到i==9,搜索完成。

下面附源代码:

#include <iostream>

#include <cstring>

#include <stdio.h>

#include <algorithm>

using namespacestd;

int hang[9][10]; //用于记录第i行中j数字是否出现过

int lie[10][9];  //用于记录第j列中i数字是否出现过

int ge[9][10];   //用于记录格子中j个数字是否出现过

struct Shudu

{

    string a;

}shudu[9];

int flag;

void print()

{

    for (int i = 0; i < 9; i++)

    {

        cout <<shudu[i].a;

        cout <<endl;

    }

}

void DFS(int m,int n)

{

    if (m == 9)

    {

        flag = 1;

        print();

        return ;

    }

    if (flag == 1)

        return ;

    if (shudu[m].a[n] != '0')

    {

        if (n == 8)

            DFS(m + 1,0);

        else

            DFS(m,n+1);

    }

    if (shudu[m].a[n] == '0')

        {

            for (int t = 1; t <= 9; t++)

            {

                int k = m / 3 * 3 + n / 3;

                if (hang[m][t] != 1 &&lie[t][n] != 1 &&ge[k][t] != 1)

                {

                    hang[m][t] = 1;

                    lie[t][n] = 1;

                    ge[k][t] = 1;

                    shudu[m].a[n] =char(t + 48);

                }

                else

                    continue;

                if (n == 8)

                    DFS(m+1,0);

                else

                    DFS(m,n+1);

                shudu[m].a[n] = '0';

                hang[m][t] = 0;

                lie[t][n] = 0;

                ge[k][t] = 0;

            }

        }

}

int main()

{

    int n;

    scanf("%d",&n);

    while (n--)

    {

        memset(hang,0,sizeof(hang));

        memset(lie,0,sizeof(lie));

        memset(ge,0,sizeof(ge));

        int i,j;

        for (i = 0; i < 9; i++)

        {

            cin >>shudu[i].a;

            for (j = 0; j < 9; j++)

            {

                if (shudu[i].a[j] != '0')

                {

                    hang[i][int(shudu[i].a[j]-'0')] = 1;

                    lie[int(shudu[i].a[j]-'0')][j] = 1;

                    int k;

                    k = i / 3 * 3 + j / 3;

                    /*

                     将整个数组分为9个格子。

                     k = 1 ,i = 0 to 2,j = 0 to 2;

                     k = 2 ,i = 0 to 2,j = 3 to 5;

                     k = 3 ,i = 0 to 2,j = 6 to 8;

                     ...........

                     k个格子即为k = i / 3 * 3 + j / 3;

                     */

                    ge[k][int(shudu[i].a[j] - '0')] = 1;

                }

            }

        }

       // for (i = 0; i < 9; i++)

        //{

          //  for (j = 0; j < 10; j++)

            //    cout << hang[i][j] << " ";

           // cout << endl;

       // }

        cout <<endl;

        flag = 0;

        DFS(0,0);

    }

    return 0;

}


对于格子的问题:

k(格子)           i(行数)         j(列数)

1                       0~2              0~2

2                       0~2              3~5

3                       0~2              6~8

4                       3~5              0~2

5                       3~5              3~5

6                       3~5              6~8 

7                       6~8              0~2

8                       6~8              3~5

9                       6~8              6~8


找关系就行……

还是从这个题中学到了很多。

争取下次标记问题可以做的更好。搜索的思路以及终止条件可以越来越清楚。

这个题对我的帮助还是很大的。