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

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

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

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(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


找关系就行……

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

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值