惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
腾讯CDC
P
Privacy & Cybersecurity Law Blog
V
Vulnerabilities – Threatpost
小众软件
小众软件
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
P
Privacy International News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Scott Helme
Scott Helme
Simon Willison's Weblog
Simon Willison's Weblog
Forbes - Security
Forbes - Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
G
Google Developers Blog
S
Secure Thoughts
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 司徒正美
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Blog — PlanetScale
Blog — PlanetScale
TaoSecurity Blog
TaoSecurity Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Last Week in AI
Last Week in AI
H
Heimdal Security Blog
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
Security Latest
Security Latest
SecWiki News
SecWiki News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Security Affairs
V2EX - 技术
V2EX - 技术
S
Schneier on Security
Stack Overflow Blog
Stack Overflow Blog
雷峰网
雷峰网
博客园_首页
AI
AI
Help Net Security
Help Net Security
I
Intezer
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
Google DeepMind News
Google DeepMind News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Exploit Database - CXSecurity.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hacker News: Ask HN
Hacker News: Ask HN
Project Zero
Project Zero
D
Docker

博客园 - 胡敏

WebSharp 3.0(个人修订版)全代码,WebSharp 的作者已经抛弃它了吗?(一个国产ORM框架) 从追MM谈Java的23种设计模式 - 太经典了,转到自己的BLOG上收藏着先 利用.net创建安全COM控件 AutoCAD二次开发之创建菜单 我的家——三维地图 生活在垃圾网络中,我们该怎么办? vs.net 2005 中文版下载 c#调用des64.dll进行加密解密 - 胡敏 - 博客园 MapXtreme 2004 6.2 中文版破解文件及安装方法(已经不提供下载) 提供MapXtreme 2004 6.2 NCP破解文件及安装方法(已经不能提供了,等待破解最新的吧) 爆笑经典签名 一句话经典笑话 MapXtreme2004新手资料续 MapXtreme2004初学者资料(整理) 移动用户查询手机开通的服务 使用 Rational XDE for .net建模和设计数据库(原创) 自己动手注册xde for .net帮助 如何得到别人收藏夹里的网址 十种你不知道的东西,绝对经典(如果你知道就不用点了,该休息了)(转)
一个数独问题的算法(已更新,提供一个简单算法,欢迎拍砖)
胡敏 · 2006-08-25 · via 博客园 - 胡敏

前段时间出差在外闲得无事看到一个数独问题。有三题,脑子不好使,只做出前两题。想想不如用程序来实现。
我先把题放出来大家有兴趣研究一下。

8

5

7

1

1

9

2

6

2

5

6

9

2

4

5

8

8

1

2

4

9

4

6

5

7

5

8

9

1


5

2

1

9

6

3

3

5

7

6

6

1

4

7

7

2

6

4

5

3

8

6

9

7

8

3

5

8

3

9

8

7


6

1

7

1

9

3

6

4

5

2

8

8

1

7

2

2

7

6

6

7

6

5

3

5

4

8

规则:
在9*9的格子中用1到9填满格子:
每一行都要用到1~9,位置不限;
每一列都要用到1~9,位置不限;
每3*3格子都要用到1~9,位置不限;

我的算法思想比较简单:穷举法,递归。
1、初始化:
 新建两个数组A[9,9],B[9,9],他们的初始值都一样。

         public  static int[,,] A = new int[9,9,9];

         public  static int[,] B = new int[9,9];

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

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

                       A[i,j] = 0;

              A[0,1]=6;

              A[0,4]=1;

              A[0,5]=7;

                   ………………

              A[8,3]=5;

              A[8,4]=4;

              A[8,7]=8;

              A[8,8]=6;


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

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

                       B[m,n] = 0;

              B[0,1]=6;

              B[0,4]=1;

              B[0,5]=7;

                   ………………

              B[8,3]=5;

              B[8,4]=4;

              B[8,7]=8;

              B[8,8]=6;

递归过程:

         public void JudgeNumber(int x,int y)

         {

              if(x<9&&y<9)                                 //判断数组下标范围

              {

                   if(A[x,y] == 0||A[x,y] != B[x,y])       //如果数组的值为零或者取得的值不等于B的值

                   {

                       for(int i=1;i<10;i++)               

                       {

                            A[x,y] = i;                     //循环付值

                            if(Pass(x,y))                   //判断条件

                            {

                                 if(Victory())              //成功

                                 {

                                     printShuzu();

                                     return ;

                                 }

                                 if(y<8)                     //判断下一个数

                                     JudgeNumber(x,y+1);

                                 else

                                     JudgeNumber(x+1,0);

                            }

                       }

                       A[x,y] = 0;                           //失败之后把值设为零,以便继续判断

                   }

                   else                                      //判断下一个数

                   {

                       if(y<8)

                            JudgeNumber(x,y+1);

                       else

                            JudgeNumber(x+1,0);

                   }

              }

         }

         public bool Pass(int i,int j)

         {

            //判断横竖有无重复

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

              {

                   if(b!=i)

                       if(A[i,j] == A[b,j])

                            return false;

                   if(b!=j)

                       if(A[i,j] == A[i,b])

                            return false;

              }

            //判断*3有无重复

              int q0 = (i/3)*3;

              int k0 = (j/3)*3;

              int q1 = (i/3+1)*3;

              int k1 = (j/3+1)*3;

              for(int q=q0;q<q1;q++)

                   for(int k=k0;k<k1;k++)

                       if(q!=i&&k!=j)

                            if(A[i,j] == A[q,k])

                                 return false;

              return true;

         }

        /// <summary>

        /// Pass情况下如果整个数组无0表示成功求解

        /// </summary>

        /// <returns></returns>

         public bool Victory()

         {

              bool ax=false;

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

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

                   {

                       if(  A[i,j] != 0)

                            ax =true;

                       else

                            return false;

                   }

              return ax;

         }


本算法的问题:
1.穷举取值过多。不必从1~9全部取
2.成功后在递归里面不能跳出。
对问题1的改进:
1.新建3维数组A[9,9,9]
2初始判断,获取该位置可取值的范围

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

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

                   {

                       int[] B = new int[9];

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

                            B[d] = d+1;

                       if(A[i,j,0]==0)

                       {

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

                            {

                                 A[i,j,0] = B[a];

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

                                 {

                                     if(b!=i)

                                          if(A[i,j,0] == A[b,j,0])

                                               B[a]=0;

                                     if(b!=j)

                                          if(A[i,j,0] == A[i,b,0])

                                               B[a]=0;

                                 }

                                 int q0 = (i/3)*3;

                                 int k0 = (j/3)*3;

                                 int q1 = (i/3+1)*3;

                                 int k1 = (j/3+1)*3;

                                 for(int q=q0;q<q1;q++)

                                     for(int k=k0;k<k1;k++)

                                          if(q!=i&&k!=j)

                                               if(A[i,j,0] == A[q,k,0])

                                                    B[a]=0;      

                                 A[i,j,0] = 0;

                            }

                       }

                   }

 3.更改判断部分.

         public void JudgeNumber(int x,int y)

         {

              if(x<9&&y<9)

              {

                   if(A[x,y,0] == 0||A[x,y,0] != B[x,y])

                   {

                       for(int i=1;i<9;i++)//更改部分

                       {

                            if(A[x,y,i]!=0)//更改部分

                            {

                                 A[x,y,0] = A[x,y,i];//更改部分

                                 if(Pass(x,y))

                                 {

                                     if(Victory())

                                     {

                                          printShuzu();

                                          //return ;

                                     }

                                     if(y<8)

                                          JudgeNumber(x,y+1);

                                     else

                                          JudgeNumber(x+1,0);

                                 }

                            }

                       }

                       A[x,y,0] = 0;

                   }

                   else

                   {

                       if(y<8)

                            JudgeNumber(x,y+1);

                       else

                            JudgeNumber(x+1,0);

                   }

              }

         }