摘自:http://www.yqshare.com/sudoku.html
很有幸,通过了华为编程大赛的初赛,进入决赛。
决赛时间是7.9号 8:00–15:00,在重庆大学。这次大赛的题目,是关于sudoku的,关于判局、求解、生成游戏。
本次比赛的题目是数独游戏相关的,我就不说了吧,百度一下,网上一大把!
在整整一天的比赛时间里,我花了一个上午的时间写一个MFC的界面,好痛苦。比赛环境,连个MSDN都没得,而且,最近这一年都一直在linux下做,很久没有MFC了。不过还好的是,把界面给做出来了。
中午和下午想了两个算法。
1)判局,也就是要判断用户,填入的数据是不是合法的,首先要判断每一行、每一列、每个九宫格,是不是仅有1-9的全部数字组成。判断这个我使用了位图算法,即,在一个int中的底9位用来匹配行中出现的数字,如果该行是由1,2,3,4,5,6,7,8,9,组成,那么该int的第九位便全部为1,否则会有为0的位,因此该bitmap肯定小于511,这样通过一次遍历就实现了一个匹配。用同样的方法遍历列,以及九宫格。只有个O(N)就可以解决这个问题了,呵呵
2)求解
这个方法应该的比较多的,一般都是DFS来求解。1.按下标blank由小到大的顺序逐个获取空白位置;
2.对空白位置blank试图填数,填数的规律为从l-9依次由小到大选择(有序);
3.若找到一个可以填人的数据(调用check(blank),检查当前字符所在的行、列、九宫格是否满足规定,若不满足,即找不到合适数据填人该位置),将数据填人sudoku[blank],并将blank入栈push;否则转5.;
4.获取下一个空白位置,若有空白位置则转2.,否则转6.;
5.进行回溯,即pop得到上一次填数的位置sp,重新对该位置试图填数,为了递推的高效性,此时可以仅从当前sp存放的数字大l开始试图填数,转(3);
6.填数结束。
注:当然还有很多其他的方法,这个是应该是比较想的,呵呵
3)生成游戏
我当时想到的就是用“挖洞”。即生成一个数独全局,然后随机挖去一部分数据即产生有解的数独布局。
用的就是编程之美的上的思想:产生一个不会重复的“九宫格”,然后对其他的九宫格,用行变换的思想去填充。这个比较简单。一下就把代码写出来了…
最后,感觉华为的这个编程大赛,组织的有些纰漏。比如:可以带书进去,但是又没有集体通知,有的同学带了、有的同学没有带,这样就有些不公平,还有就是,写算法就不要让大家做MFC吗,做MFC就不能算是真正意义上的编程大赛咯!我就是浪费了很多时间到MFC上,估计其他同学也和我差不多,呵呵
这次回来,我突然有买一本《算法导论》回来看的冲动了,虽然自己平常也很注重学习算法,但是,总感觉知识储备不够…