解题思路

开始的解题思路

1.前两部分其实是一个问题,它是ACM中经典的解数独的问题,基本的思路设计也一样利用dfs回溯搜索+剪枝优化.
(1)生成数独终局可以用三个二位数组来分别记录每一列,每一行,每个3*3网格中1-9的分配情况,已分配记为1,未分配记为0.
	在一位数组1-9全排列的基础上,使用dfs逐个向网格中填入数字.
(2)解数独同理使用这三个数组,同时记录要填入的0的位置.然后使用dfs逐个空位将空余数字填入棋局.
2.最后一部分设计界面,由于使用的是c++,考虑使用MFC还是Qt.考虑到自身想尝试一下Qt,而且与Qt相比MFC缺点太多.
所以这里使用Qt设计简单的GUI界面.相关的对象,信号槽使用可以查询Qt的说明文档.
设计界面的同时,要完成数独游戏,还要设计两个功能:
(1)在生成数独终局中挖30-60个空位.思路是先在每个3*3的网格中随机挖2个空位以满足题目要求,然后在全局中挖去剩余的空位.
	其中主要是要将9*9的格子从0-80编号,挖空就是从81个编号中随机除去某个编号.最后和棋盘对比,将除去的数字置为0.
(2)提交判断数独是否完成,每填入一个数更新一下棋盘对象和三个数组,若对应的三个数组中有数字出现2次则数独失败.

性能测试后修改解题思路

在发现生成1000000个数独后效果不佳,时间耗时太长.在查询相关资料,发现原来的算法存在重大的缺陷.本题在第一个数字固定的情况下,是对1-8的全排列,而这只有8!=40320个.
因此打算对40320个数独进行行列交换.此处为了确保数独的不重复,不更改第一行的基础排列,只对第(2,3)(4,5,6)(7,8,9)行进行组内行交换.同时为了保证不重复,最后最多可以得到8!26*6=2903040个不重复的数独,符合最大1000000个数独的要求.而且进行行列交换的时间远比进行DFS要快.
在这里插入图片描述

证明合法

此时要证明生成的数独是否合法?
要证明两点:1.生成的数独是否符合数独要求.2.生成的数独是否重复.
1.生成的数独是否符合数独要求.
首先可以肯定根据深搜算法dfs生成的数独肯定符合数独本身的要求.
因此要证明行交换生成的数独是否符合要求
(1)每次交换是一整行进行交换的,所以交换后的这两行也是符合行1-9不重复的要求.
(2)进行行交换的每个数字所属的列号是不会发生变化,所以交换前的数独符合列要求那交换后一定会符合列要求.
(3)这里进行的行交换,只是进行局部的行交换,交换的行没有超出它所属的3*3方格…所以交换的行上的数字所属的3 * 3方格不变.所以满足3.*3方格要求.
综上生成的数独符合要求.
2.生成的数独是否重复.
要保证生成的数独不重复.
(1)首先要保证每一组数独中使用DFS生成的基础数独不重复.所以只能使用·Rand随机生成第一个DFS基础数独的基础1-9数列.然后使用全排列生成剩下所有DFS基础数独的基础1-9数列.这样保证所有DFS基础数独的第一行数列(即基础数列)是1-9全排列中不相同的一种.因此这些DFS基础数独不重复.而第一个数字固定为9.所以只能生成1-8的全排列.最多生成8!=40320个DFS基础数独.
(2)保证每一个进行行交换生成的数独不重复…由于行交换不交换第一行基础数列.所以每一个基础DFS数独和基于该数独行交换的数独组成一组.所以不同组的两个数独一定不重复.只需要证明组间的数独不重复.而组间的数独是由于行交换的来的.它们的第一列都是1-9的全排列.在算法交换的时候就保证了每一个第一列全排列是不重复的.最多40320组每组最多可以有2!*3!*3!=72个.所以一共最多可以有2903040个不重复的数独.

进一步优化思考

行交换明显所需的时间比DFS要短.那么可以在进行列交换进一步降低所需要的时间.
但是我无法证明进行行列交换后的两个不同组的数独是否不重复.
经过文档查询可知,在宫内交换可以保证重复性和正确性.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值