puzzle(0311)《棋盘》内固、外固

棋盘与皇后:内固数、外固数与N皇后问题探讨
本文详细分析了棋盘上的内固数和外固数,探讨了马的内固问题和外固问题,并提供了8*8棋盘上马的外固集解决方案。同时,文章介绍了经典的8皇后问题及其变种N皇后问题,包括解的数量和不同放置方法。最后,提到了无穷皇后问题和严格N皇后问题的轮胎模型,以及6*6和8*8棋盘上皇后的外固数。

目录

一,内固、外固

内固和外固的关系

二,马的内固问题

三,马的外固问题

四,八皇后问题

五,N皇后问题

HDU 2553 N皇后问题

力扣 51. N皇后

力扣 52. N皇后 II

六,无穷皇后问题

1,无穷皇后问题

2,迭代法的正确性

3,严格N皇后

4,严格N皇后问题的轮胎模型

5,严格N皇后问题和幻方

七,皇后的外固问题

1,6*6

2,8*8


一,内固、外固

在一个图中可以选出一组点,使得其余的点至少与这组点中某一个点相邻,选出的这组点称为图的一个外固集,外固集中所含点数的最小值称为外固数。

在一个图中可以选出一组点,使得任意两点都不相邻,选出的这组点称为图的一个内固集,内固集中所含点数的最大值称为内固数。

内固和外固的关系

显然,内固数 ≥ 外固数

已经被证明,N>3时N皇后问题有解,所以它的内固数等于外固数。

马的內固数是(n*n+1)/2,而外固数则复杂一些,8*8的棋盘中外固数是12,内固数是32。

最大内固集(即内固数对应的内固集)一定也是个外固集,反之,最小外固集却不一定是内固集

是否存在一个图,存在它的一个内固集也是外固集,其中所含点数既不是内固数也不是外固数?

感觉应该是存在的。

二,马的内固问题

n*n的棋盘上(n>4)最多可以放多少个马,使得它们互不攻击,即马的内固数是多少。

如果n=2*k,因为有一个哈密顿圈,圈的大小是4*k*k,所以内固数不超过2*k*k,即n*n/2。

如果n=2*k+1,因为有一个哈密顿链,圈的大小是4*k*k+4*k+1,所以内固数不超过2*k*k+2*k+1,即(n*n+1)/2。

我们将棋盘按照国际象棋的棋盘来染色,使得白色的格子数-黑色的格子数=0或1。

也就是说,白色格子有(n*n+1)/2个,在所有的白色格子里面放马,这些马都不能互相攻击。

所以,马的內固数是(n*n+1)/2

三,马的外固问题

对于8*8的棋盘,求马的外固数和外固集

所以外固数自然是12了,那么外固集有哪些呢?

我的解法:(下面所有的内容都是自己想的,后来才看到书上这一页)

初始代码是用24层的循环进行找答案试试,虽然要运行结束不太现实,但是如果运气好,循环只进行一部分就得到一部分答案,也不是不可能。

<iostream>
using namespace std;

void exist(int list[][8], int i, int j)		//将可以到达的8个(或少于8个)格子记录下“已经覆盖”
{
	if (i > -1 && i<8 && j>-1 && j < 8)list[i][j] = 1;
}

void place_a_horse(int list[][8], int i, int j)		//更新已经覆盖的格子的信息
{
	list[i][j] = 1;
	exist(list, i - 2, j - 1);
	exist(list, i - 2, j + 1);
	exist(list, i - 1, j - 2);
	exist(list, i - 1, j + 2);
	exist(list, i + 2, j + 1);
	exist(list, i + 2, j - 1);
	exist(list, i + 1, j + 2);
	exist(list, i + 1, j - 2);
}

void action(int list[][8], int i1, int j1, int i2, int j2, int i3, int j3, int i4, int j4, int i5, int j5, int i6, int j6, int i7, int j7, int i8, int j8, int i9, int j9, int ia, int ja, int ib, int jb, int ic, int jc)
{
	for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)list[i][j] = 0;
	place_a_horse(list, i1, j1);		//放入12个棋子
	place_a_horse(list, i2, j2);
	place_a_horse(list, i3, j3);
	place_a_horse(list, i4, j4);
	place_a_horse(list, i5, j5);
	place_a_horse(list, i6, j6);
	place_a_horse(list, i7, j7);
	place_a_horse(list, i8, j8);
	place_a_horse(list, i9, j9);
	place_a_horse(list, ia, ja);
	place_a_horse(list, ib, jb);
	place_a_horse(list, ic, jc);

for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)if (list[i][j] == 0)return;
cout << i1 << j1 << i2 << j2 << i3 << j3 << "  " << i4 << j4 << i5 << j5 << i6 << j6 << "  ";
cout << i7 << j7 << i8 << j8 << i9 << j9 << "  " << ia << ja << ib << jb << ic << jc << endl;
cout << list[2][0] << endl;
}

//12个棋子从上往下遍历循环
void visit12(int list[][8])
{
	for (int i1 =  0; i1 < 3; i1++) for (int j1 = 0; j1 < 8; j1++)
	for (int i2 = i1; i2 < 3; i2++)	for (int j2 = 0; j2 < 8; j2++)
	for (int i3 = i2; i3 < 3; i3++)	for (int j3 = 0; j3 < 8; j3++)
	for (int i4 = i3; i4 < 3; i4++)	for (int j4 = 0; j4 < 8; j4++)

	for (int i5 = i4; i5 < 8; i5++)	for (int j5 = 0; j5 < 8; j5++)
	for (int i6 = i5; i6 < 8; i6++)	for (int j6 = 0; j6 < 8; j6++)
	for (int i7 = i6; i7 < 8; i7++)	for (int j7 = 0; j7 < 8; j7++)
	for (int i8 = i7; i8 < 8; i8++)	for (int j8 = 0; j8 < 8; j8++)

	for (int i9 =  5; i9 < 8; i9++) for (int j9 = 0; j9 < 8; j9++)
	for (int ia =  5; ia < 8; ia++) for (int ja = 0; ja < 8; ja++)
	for (int ib =  5; ib < 8; ib++) for (int jb = 0; jb < 8; jb++)
	for (int ic =  5; ic < 8; ic++) for (int jc = 0; jc < 8; jc++)
		action(list, i1, j1, i2, j2, i3, j3, i4, j4, i5, j5, i6, j6, i7, j7, i8, j8, i9, j9, ia, ja, ib, jb, ic, jc);
}


int main()
{
	int list[8][8];
	visit12(list);
	cout << "end";
	system("pause>nul");
	return 0;
}

结果运气并不好,得不到答案。

于是我决定尝试先找找有没有非常规则的答案。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值