puzzle(0112)不规则数独、变种数独

本文探讨了不规则数独的对称特性,如中心对称、对角线对称等,并展示了各种变种数独如倍数数独、武士数独的规则及求解技巧。重点讲述了规则退化现象在解题过程中的应用。

目录

一,不规则数独

1,规则

2,对称性

含正方形的不规则数独

中心对称的不规则数独

其他对称不规则数独

3,计算机求解

二,变种数独

1,规则

2,对角线数独

3,窗口数独

4,超级窗口数独

5,奇偶数独

情人节趣味数独

6,摆造型的数独

年字数独

京字数独

7,连续数独

8,连续数独2

9,箭头数独

10,边框数独

边框奇偶数独

摩天楼数独

11,满覆盖杀手数独

计算机求解V1

计算机求解V2

计算机求解V3

12,非满覆盖杀手数独

计算机求解V1

计算机求解V2

13,倍数数独

14,不等式数独

15,武士数独

16,变种数独的规则退化现象


一,不规则数独

在线play

1,规则

没有分9个宫,而是用特定的线分成9个区,其他规则和标准数独一样。

2,对称性

在我做过的这些不规则数独里面,居然全部有着对称性!

有的是格子有对称性,有的是数字有对称性,还有的是格子和数字都有对称性。

对称性又分很多很多种。

含正方形的不规则数独

这5个不规则数独,正中间都是正方形,而且里面给出的数字都是对称分布的。

具体说来

图一的格子是中心对称的,数字几乎是中心对称的。

图二的格子和数字都是左右对称的

下面一行的三个图,格子和数字都是中心对称的

这个图有2个正方形,也是格子和数字都是中心对称的。

这个图有3个正方形,格子是关于主对角线对称的,而数字是关于2条对角线都对称的。

中心对称的不规则数独

不规则数独有很多很多都是格子成中心对称的,比如下面这个:

然而更可怕的是,有的数独在此基础上,数字的位置也有着规律。

这3个数独,数字也是成中心对称的

   

这2个数独还是挺像的,而且,数字的位置,都是关于2个对角线对称的。

关于2个对角线对称是中心对称里面的一种,比一般的中心对称更具有对称美。

   

这3个数独,数字都是90°旋转对称。

90°旋转对称是中心对称里面的一种,比一般的中心对称更具有对称美。

    

这3个数独,一看就是非常非常对称,上下对称,左右对称,对角线对称,90度旋转对称

其他对称不规则数独

格子是关于副对角线对称的,而数字是上下对称而且左右对称

格子是左右对称的

格子是左右对称的,而数字是关于副对角线对称的。

格子是关于副对角线对称的,而数字是左右对称的。

3,计算机求解

前面我给出了用于求解任何规则数独的代码,这里我将对代码进行修改,得到可以用于求解任何不规则数独的代码。

不规则数独和规则数独的区别,在于划分9个区的方式不同,规则数独是9个3*3的正方形区,而不规则数独的分区各种各样的。

只需要用1个数组par记录如何分区,即可求解不规则数独。

代码:

#include<iostream>
using namespace std;

int list[10][10];
int par[10][10];		//par[i][j]=n
int anti[10][10];		//anti[n][?]=i*10+j;

void init()
{
	cout << "输入数字,没有数字的用0代替" << endl;
	char c;
	for (int i = 1; i < 10; i++)for (int j = 1; j < 10; j++)
	{
		cin >> c;
		list[i][j] = c - '0';
	}
	cout << "输入每个格子属于哪一块(1-9)" << endl;
	for (int i = 1; i < 10; i++)for (int j = 1; j < 10; j++)anti[i][j] = 0;
	for (int i = 1; i < 10; i++)for (int j = 1; j < 10; j++)
	{
		cin >> c;
		par[i][j] = c - '0';
		for (int k = 1; k < 10; k++)if (anti[par[i][j]][k] == 0)
		{
			anti[par[i][j]][k] = i * 10 + j;
			break;
		}
	}
}

bool ok(int i, int j, int k)
{
	for (int jj = 1; jj < 10; jj++)if (list[i][jj] == k)return false;
	for (int ii = 1; ii < 10; ii++)if (list[ii][j] == k)return false;
	int p = par[i][j];
	for (int ii = 1; ii < 10; ii++)
		if (list[anti[p][ii] / 10][anti[p][ii] % 10] == k)return false;
	return true;
}

bool trys(int i, int j)
{
	if (j == 10)
	{
		i++;
		j = 1;
	}
	if (i == 10)return true;
	if (list[i][j])return trys(i, j + 1);
	for (int k = 1; k < 10; k++)
	{
		if (ok(i, j, k))
		{
			list[i][j] = k;
			if (trys(i, j + 1))return true;
		}
	}
	list[i][j] = 0;
	return false;
}

void out()
{
	for (int i = 1; i < 10; i++)
	{
		for (int j = 1; j < 9; j++)cout << list[i][j] << " ";
		cout << list[i][9] << endl;
	}
}

int main()
{
	init();
	trys(1, 1);
	out();
	system("pause>nul");
	return 0;
}

在ok函数中,由任何一个格子的坐标,需要直接得到其他所有格子的坐标,所以需要一个数组anti将par反过来记录。

其实不用这个数组也行,大不了在ok里面做一个搜索,搜索81个格子,根据par值判断是否在一个区。

这样做,代码稍微简单一点点,虽然复杂度是一样的,但是时间肯定慢一些。

上面的代码,对于任何不规则数独,应该都能在2秒之内输出答案。

用法示例:

对于这个数独,将空格全部补0:

030159080
209000603
007803400
900040005
706000108
300090006
002907500
501000802
070516020

然后,将9个区编号1-9:

然后同样的变成9*9的方阵:

122333444
122333444
122233444
125253666
115555566
111859596
777889996
777888996
777888996

将这2个9*9的方阵输入程序即可得到答案:

所以答案是:

二,变种数独

1,规则

变种数独是在规则数独的基础之上,加一点点特殊的规则。

这些规则,有的也可以加在不规则数独之上,不过比较少见。

因为多了一些约束,所以相对来说,一般来说给出的数字比较少。

变种数独里面,有很多都是规定一些大小为9的区域,这些区域里面都是1到9的数字。

2,对角线数独

在规则数独的基础上,还要满足2条对角线也是1到9

比如这个:

除了很对称之外,好像没什么特点。

但是,这个数独很特殊,要自己去解才能体会。

在解这个数独的时候,你会感觉,这个数独几乎有一套独特的推理规则,

规则数独常用的方法在这里很不好用。

规则数独,用行唯一性、列唯一性是最多的。

而这个数独,行唯一性、列唯一性用的很少,反而对角线用的很多很多!

 然而,比对角线用的更多的,是一个奇特的规律,仅对本数独有效!

这个规律我不明说,在下面的答案我用图画出来

对角线的规则可以叠加在其他变种数独之上,比如窗口数独,

也可以叠加在不规则数独之上。

3个奇特的数独:

    

这3个数独,一看就都有着较强的对称性。

然而,不仅是对称性,任何2个数字之间的曼哈顿距离都是偶数!

也就是说,如果把数独按照如下方式染色的话

这3个数独的所有数字都会被黑格子盖住!

他们的解分别是:

    

第一个数独很难,第二个数独难度普通,第三个数独很简单。

他们给出的初始数字分别有24、28、24个,但是因为结构差异很大,所以难度差别大。

这3个数独,共性很明显,却又都有着很独特的结构,解法截然不同,

而且都和普通的规则数独解法不太像,这些,只有自己去解才能体会的到!

3,窗口数独

在规则数独的基础上,还要满足4个灰色的宫也是1到9

答案:

4,超级窗口数独

在规则数独的基础上,还有9个块也都是1到9

约束比较多,答案:

5,奇偶数独

变种数独里面,还有各种奇偶数独,就是标出特定的区域必须是奇数或者必须是偶数。

情人节趣味数独

情人节趣味数独这个是奇偶数独的一种。

这个趣味数独的规则和规则数独差不多,只是标出了16个格子必须是偶数。

求解的过程也很有趣:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值