暑假练习--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


找关系就行……

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

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

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值