前些日子,有人网上说解决了什么最难数独什么的,然后下面一片欢呼 -- 我看了下所谓题目,无非一个普通的9*9的小题目而已,机器完全可以轻松遍历。 感觉很不可思议 -- 在这种信息时代,计算机能轻松遍历的东西,就不算什么难题,让人闲暇时候玩玩就算了,拿来当作学术成就什么来炫耀,实在有些。。。坐什么观什么了。
正事做着,debug 很烦恼,所以随便写个数独的解决来调节下身心健康。
数独有规则如下:
9*9
空格中,填入 1~9 这 9 个数字某个- 每行,每列的9个数字不可重复。
- 将
9*9
的区域分为3*3
个3*3
格的区域,每个区域内部不可重复
实现如下:
1. 每行不可重复
在初始化的时候,未填写的位置是 0, 所以不会影响到别的数据。
然后就是行坐标不变,列坐标一个一个试探,如果都不相同说明是可以用的。
int Horizontal(int a[9][9],int abscissa,int ordinate,int test) { int i; for(i=0;i<9;i++) if(a[abscissa][i] == test)return 0; return 1; }
2. 每列不可重复
每列不可重复其实和每行不可重复是相似的,只是一个是行坐标不变,一个是列坐标。
int Vertical(int a[9][9],int abscissa,int ordinate,int test) { int i; for(i=0;i<9;i++) if(a[i][ordinate] == test) return 0; return 1; }
3. 小区域不可重复
首先检查待测试的代码所在区域(其实就是横向3个区域,纵向3个区域)。
然后比较和前两个一样。
int Area(int a[9][9],int abscissa,int ordinate,int test) { int i,j; int absMin = (abscissa/3)*3; int absMax = (abscissa/3+1)*3; int ordMin = (ordinate/3)*3; int ordMax = (ordinate/3+1)*3; for(i=absMin;i<absMax;i++) for(j=ordMin;j<ordMax;j++) if(test == a[i][j]) return 0; return 1; }
4. 递归试探
传入的是一个已经填写了一半的数组和一个offset,offset的值是0~80共81个,如果超过这个,说明完美完结了,否则继续判断。
如果是非0,则递归自己,填写下个offset,否则从1~9逐个试探是否可以填写。若可以,填写,否则清0本次数据,测试下个。直到可以或者终于确定这条路走不痛,返回是或者否。
inline int AllDone(int a[9][9],int abscissa,int ordinate,int test) { if(!Horizontal(a,abscissa,ordinate,test)) return 0; if(!Vertical(a,abscissa,ordinate,test)) return 0; if(!Area(a,abscissa,ordinate,test)) return 0; return 1; } int nextData(int a[9][9],int offset) { if(offset >= 81) return 1; int i; int abs = offset/9; int ord = offset%9; if(a[abs][ord]!=0) { return nextData(a,offset+1); } for(i=1;i<10;i++) { if(AllDone(a,abs,ord,i)) { a[abs][ord] = i; if(nextData(a,offset+1)) { return 1; } } a[abs][ord] = 0; } return 0; }
5. 输出
如题。输出就是个简单的控制。
每行输出9个,输出9行即可。
int output(int a[9][9]) { int i,j; for(i=0;i<9;i++) { for(j=0;j<9;j++) printf("%d ",a[i][j]); printf("\n"); } return 1; }
6. main函数
main函数读取9*9个数字,然后递归开搞。
如果无法搞,显示无解,否则显示解。
int main() { int a[9][9]; int i; int j; memset(a,0,sizeof(a)); for(i=0;i<9;i++) { for(j=0;j<9;j++) { scanf("%d",&a[i][j]); } } if(nextData(a,0)) { printf("get result:\n"); output(a); }else { printf("no result.\n"); } return 0; }
当然,参数列表什么的,有些没有用到,回头再改,反正不是在做的正事。
输出测试
[yu@argcandargv-com Sudoku]$ make run INPUT: 0 0 0 0 0 0 4 5 0 0 0 7 0 0 0 3 0 0 1 0 9 0 6 0 0 0 0 3 0 0 0 0 0 0 0 0 5 0 0 4 0 0 0 0 0 0 0 0 0 7 0 0 0 9 0 0 1 2 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 6 0 0 0 0 0 7 OUTPUT: get result: 8 6 3 7 9 2 4 5 1 2 5 7 1 8 4 3 9 6 1 4 9 5 6 3 8 7 2 3 9 8 6 2 1 7 4 5 5 7 2 4 3 9 6 1 8 6 1 4 8 7 5 2 3 9 9 8 1 2 4 7 5 6 3 7 2 5 3 1 6 9 8 4 4 3 6 9 5 8 1 2 7 CORRECT?
工程位置如下:
有人有兴趣,可以拿过去玩玩。
需要说明的是, 这个纯粹是暴力跑. 有很多方法可以很容易优化, 只是没有做而已.
此外, leetcode 有一道题也是讲数独的, 我为此准备了一个解在此处.
38 Comments
Leniy · February 7, 2014 at 09:28
怎么又想起来更新这篇文章了?
yu · February 7, 2014 at 12:57
@Leniy 删掉了1/3不喜欢的旧文,这个估计是一不小心更新的吧
Leniy · February 7, 2014 at 12:58
@Yu Jing 你修改评论的速度好快
yu · February 7, 2014 at 12:59
@Leniy 其实是不小心f5了下
Leniy · February 7, 2014 at 13:00
@Yu Jing 评论中的“的”的位置不一样啊
yu · February 7, 2014 at 13:02
@Leniy 就是不小心刷了下网页修改后重新提交,结果被判定为提交了两次,然后后台把第一次删掉这样的操作过程啊。
Leniy · February 7, 2014 at 13:03
@Yu Jing soga。你们开学没?
yu · February 7, 2014 at 13:04
@Leniy 实验室coding …顺手处理邮件之类的什么中
Leniy · February 7, 2014 at 13:05
@Yu Jing 好羡慕
Vespa · January 5, 2014 at 20:12
以前大一也写过数独的全解程序,也是C++,也是这条思路。。
yu · January 5, 2014 at 20:25
@Vespa 哈,9*9,遍历一遍都是小意思,轻松就能暴力,何乐而不为
小草元 · July 5, 2013 at 23:39
数独挺流行的,但我至今不了解其玩法。
看博主的解决方法没有理解。手机上看的难受,明天电脑再仔细顽味下。总感觉你的思路说的不清楚。。。或许还是我理解不到位
yu · July 6, 2013 at 19:56
表示其实就是最普通粗暴的遍历而已..谈不上思路
reizhi · May 1, 2013 at 22:35
当然,这种能够遍历/枚举的数学问题用编程再好不过了
yu · May 2, 2013 at 13:15
的确
这类东西和代码真是专业对口
Leniy · April 25, 2013 at 15:02
git管理感觉麻烦啊。还要同步
yu · April 25, 2013 at 15:09
设置好hook后push上去直接部署master那个branch
Leniy · April 25, 2013 at 15:31
git我只用过github给的那个软件
yu · April 25, 2013 at 16:08
github只是其中一个托管商而已。git对服务器要求不高,可以是任何的空间,https ssh连接都可以,对服务器配置也几乎没有要求。
超好用呢
Leniy · April 26, 2013 at 15:58
我能把自己的空间换成git管理么?
yu · April 26, 2013 at 17:44
可以。
我用的是自带的,不过自己写也很容易实现。
这东西在回复里面不能说的太细,我写个新的帖子说说吧。
Leniy · April 25, 2013 at 15:44
为嘛刚刚用python给你的站点post数据没有成功啊
yu · April 25, 2013 at 16:07
不知道…
难道cache问题
Leniy · April 25, 2013 at 07:52
能评论了么
yu · April 25, 2013 at 09:51
原来的IP被墙了,但是CDN转发没问题。
本来打算用CDN完全替代原IP用的,但CDN不怎么给力,老是拿缓存骗人。。。囧。。
另,评论通知邮件工作正常否?
Leniy · April 25, 2013 at 15:43
然后没见到邮件
yu · April 25, 2013 at 21:10
这个回复的邮件能否看到?
调了下插件,发现插件暗藏玄机。。所以,你从没有收到过这个小站发出的邮件提示。。。。?
Leniy · April 26, 2013 at 07:55
收到了。以前收到过几次,后来就没有反应了
yu · April 25, 2013 at 09:56
然后我换了个主机。。。
迁移数据麻烦了点,但搞主机什么的贼方便
用git管理就是爽
Leniy · April 25, 2013 at 15:03
我过几个月准备把我的博客放到dreamhost的主机上。目前只用那个主机的ssh功能,感觉很浪费啊
yu · April 25, 2013 at 15:12
$15 / month per month ?
看介绍配置很赞啊,不知道用起来怎么样。
等我自己赚钱了再转付费的吧。。。
Leniy · April 25, 2013 at 15:24
$119/y
和同学合租的。每人才几十元
yu · April 25, 2013 at 15:40
哦,对…root权限的vps可以自己配环境,N多个网站可以一起用的哈。。。
Leniy · April 25, 2013 at 15:51
不是vps
yu · April 25, 2013 at 16:05
web hosting 也可以多domain不混?
之前还不知道
Leniy · April 25, 2013 at 16:06
看主机是不是提供了
t.k. · April 24, 2013 at 18:53
没有玩过数独的路过。。
yu · April 24, 2013 at 19:53
我也不会 —
不过这并不妨碍代码轻松完破这些所谓难题