数独生成和求解

数独生成和求解

项目地址
解题思路
1.生成
对一个合法的数独进行整行或整列的交换,所得数独仍然合法。在固定左上角数字的情况下,一个固定的数独可以变换出2!*3!*3!*2!*3!*3!=5184个不同的数独,由此只需得到200个不能通过整行整列交换使彼此相同的固定数独即可。可对第一个固定数独的每个九宫格进行全排列得到。
2.求解
求解算法参考了李显龙的数独求解算法
把1到9逐一放到数独中去,然后验证是否是合法数独。如果是合法的将数字放入数独中去,对新的数独做递归,直到填满整个数独。

实现过程
类:输入处理
函数:数独生成(create,exchange,save),数独求解(solution,solve,place,nextseq)
流程图
流程图
单元测试设计(结果可见于性能分析)
生成1000000个数独;
求解最难数独;
性能分析和改进

生成1000000个数独进行测试(附clock函数计时)

生成测试
在这里插入图片描述
求解最难数独(vs的性能分析不知道什么原因在求解时运行不了)
在这里插入图片描述
在这里插入图片描述
于是采用了clock函数计时
在这里插入图片描述
时间基本在0.02s以内
改进思路: 生成一个输出一个改为存储下来一起输出;最初暴力求解,后参考李显龙的求解算法进行修改。
消耗最大的函数:create(生成数独)
关键代码

void create(int n)
{
	int a[9] = { 1,2,9,4,5,6,7,8,3 };
	while (1)
	{
		shudu[0][0] = shudu[1][6] = shudu[2][3] = shudu[3][2] = shudu[4][8] = shudu[5][5] = shudu[6][1] = shudu[7][7] = shudu[8][4] = 3;
		shudu[0][1] = shudu[1][7] = shudu[2][4] = shudu[3][0] = shudu[4][6] = shudu[5][3] = shudu[6][2] = shudu[7][8] = shudu[8][5] = a[1];
		shudu[0][2] = shudu[1][8] = shudu[2][5] = shudu[3][1] = shudu[4][7] = shudu[5][4] = shudu[6][0] = shudu[7][6] = shudu[8][3] = a[0];
		shudu[0][3] = shudu[1][0] = shudu[2][6] = shudu[3][5] = shudu[4][2] = shudu[5][8] = shudu[6][4] = shudu[7][1] = shudu[8][7] = a[5];
		shudu[0][4] = shudu[1][1] = shudu[2][7] = shudu[3][3] = shudu[4][0] = shudu[5][6] = shudu[6][5] = shudu[7][2] = shudu[8][8] = a[4];
		shudu[0][5] = shudu[1][2] = shudu[2][8] = shudu[3][4] = shudu[4][1] = shudu[5][7] = shudu[6][3] = shudu[7][0] = shudu[8][6] = a[3];
		shudu[0][6] = shudu[1][3] = shudu[2][0] = shudu[3][8] = shudu[4][5] = shudu[5][2] = shudu[6][7] = shudu[7][4] = shudu[8][1] = a[2];
		shudu[0][7] = shudu[1][4] = shudu[2][1] = shudu[3][6] = shudu[4][3] = shudu[5][0] = shudu[6][8] = shudu[7][5] = shudu[8][2] = a[7];
		shudu[0][8] = shudu[1][5] = shudu[2][2] = shudu[3][7] = shudu[4][4] = shudu[5][1] = shudu[6][6] = shudu[7][3] = shudu[8][0] = a[6];
		memcpy(record, shudu, sizeof(shudu));
		for (int i1 = 0; i1 < 2; i1++)
			for (int i2 = 0; i2 < 6; i2++)
				for (int i3 = 0; i3 < 6; i3++)
					for (int j1 = 0; j1 < 2; j1++)
						for (int j2 = 0; j2 < 6; j2++)
							for (int j3 = 0; j3 < 6; j3++)
							{
								exchange(i1, i2, i3, j1, j2, j3);
								if (countnum == n)
								{
									FILE* out;
									fopen_s(&out, "sudoku.txt", "wt");
									fputs(result, out);
									fclose(out);
									return;
								}
							}
		next_permutation(a, a + 8);
	}

}
void exchange(int x1, int x2, int x3, int y1, int y2, int y3)
{
	memcpy(record, shudu, sizeof(shudu));
	if (x1 == 1) colexchange(1, 2);
	switch (x2)
	{
	case 1:
		colexchange(4, 5);
		break;
	case 2:
		colexchange(3, 4);
		break;
	case 3:
		colexchange(3, 4);
		colexchange(4, 5);
		break;
	case 4:
		colexchange(3, 5);
		colexchange(4, 5);
		break;
	case 5:
		colexchange(3, 5);
		break;
	}
	switch (x3)
	{
	case 1:
		colexchange(7, 8);
		break;
	case 2:
		colexchange(6, 7);
		break;
	case 3:
		colexchange(6, 7);
		colexchange(7, 8);
		break;
	case 4:
		colexchange(6, 8);
		colexchange(7, 8);
		break;
	case 5:
		colexchange(6, 8);
		break;
	}
	if (y1 == 1) rowexchange(1, 2);
	switch (y2)
	{
	case 1:
		rowexchange(4, 5);
		break;
	case 2:
		rowexchange(3, 4);
		break;
	case 3:
		rowexchange(3, 4);
		rowexchange(4, 5);
		break;
	case 4:
		rowexchange(3, 5);
		rowexchange(4, 5);
		break;
	case 5:
		rowexchange(3, 5);
		break;
	}
	switch (y3)
	{
	case 1:
		rowexchange(7, 8);
		break;
	case 2:
		rowexchange(6, 7);
		break;
	case 3:
		rowexchange(6, 7);
		rowexchange(7, 8);
		break;
	case 4:
		rowexchange(6, 8);
		rowexchange(7, 8);
		break;
	case 5:
		rowexchange(6, 8);
		break;
	}
	save();
}
int NextSeq(int S)
{
	int S2, Square, Possibles, BitCount;
	int T, MinBitCount = 100;

	for (T = S; T < 81; T++)
	{
		Square = Sequence[T];
		Possibles = Block[InBlock[Square]] & Row[InRow[Square]] & Col[InCol[Square]];
		BitCount = 0;
		while (Possibles)
		{
			Possibles &= ~(Possibles & -Possibles);
			BitCount++;
		}

		if (BitCount < MinBitCount)
		{
			MinBitCount = BitCount;
			S2 = T;
		}
	}

	return S2;
}


void Place(int S)
{
	LevelCount[S]++;
	Count++;

	if (S >= 81)
	{
		PrintArray();
		return;
	}

	int S2 = NextSeq(S);
	SwapSeqEntries(S, S2);

	int Square = Sequence[S];

	int 	BlockIndex = InBlock[Square],
		RowIndex = InRow[Square],
		ColIndex = InCol[Square];

	int 	Possibles = Block[BlockIndex] & Row[RowIndex] & Col[ColIndex];
	while (Possibles)
	{
		int valbit = Possibles & (-Possibles); // Lowest 1 bit in Possibles
		Possibles &= ~valbit;
		Entry[Square] = valbit;
		Block[BlockIndex] &= ~valbit;
		Row[RowIndex] &= ~valbit;
		Col[ColIndex] &= ~valbit;

		Place(S + 1);

		Entry[Square] = BLANK; // Could be moved out of the loop
		Block[BlockIndex] |= valbit;
		Row[RowIndex] |= valbit;
		Col[ColIndex] |= valbit;
	}

	SwapSeqEntries(S, S2);
}

时间分配

stages预估耗时/分钟实际耗时/分钟
计划3035
-估计耗时3035
开发15002000
-需求分析3035
-生成设计文档3530
-设计复审2025
-代码规范6050
-具体设计6090
-具体编码7501000
-代码复查90120
-测试400600
报告120150
-测试报告3040
-计算工作量3045
-总结/改进计划6065
合计16502185
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值