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

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - 胡敏

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);

                   }

              }

         }