六角幻方暴力填数

六角幻方暴力填数

在这里插入图片描述
题目就是上面图了 感兴趣自己搜一下原题
几何推理:
已知所有数的范围是从1-19并且没有重复,一共有15条边,并且每条边的数相等
一个点在三种边都各出现一次
15条边列15个表达式
每个点在所有的表达式当中都出现3次
所以15每条边的和=3(1+2+3…+19) ->每条边的和就是38
本来我们要枚举17个点(17重循环)
来找满足题目要求的答案
现在拥有了性质可以做到只需要枚举5个点来找到答案
我们用暴力搜索的思想来做就是:
确定5个未知数的位置 假设我们知道
我们就枚举这五个未知数的值
然后剩余的点用这些未知数来表示
最后用条件约束 所有都满足的就是答案

具体就是第一行
15 13 10 已经是固定的了

所以就确保剩下的16个数在1-19范围里,并且不重复
然后二级结论每种线的和都是38,所以只要暴力梅举5个数(不重复,在范围内),然后11个数都能表示出来了,然后还是要求这11个数在范围里不重复。
只要上述某个地方不符合条件就 return
在这里插入图片描述我这里未知数的放法是逆时针
从左边看起,最左的y=x+b的边
只有三个点 并且15已知 所以只要有用一个未知数x1表示中间的那个点
下面那个点A就能用未知数表示出来了
然后下面三个点到右边三个点再到上面三个点也是同理
最后发现只要x5放第二行中间的位置(左右都可以) 其他的点也跟着可以表示出来了 我这里表示出来的顺序就是从A-K
然后我定义A-K点为a[0],a[6],a[7]…a[15]
在这里插入图片描述
接下来就是把这些点用未知数表示
然后满足两个条件(不重复,在范围内)
就加入集合
直到19个数都加入集合了就是答案
史山

#include  <iostream>
#include <set>
using  namespace  std;
int  a[19];

void  tiaojian() {
	set<int> s;
	s.insert(15), s.insert(13), s.insert(10);
	if (!s.count(a[1]))
		s.insert(a[1]);
	else
		return;
	if (!s.count(a[2]))
		s.insert(a[2]);
	else
		return;
	if (!s.count(a[3]))
		s.insert(a[3]);
	else
		return;
	if (!s.count(a[4]))
		s.insert(a[4]);
	else
		return;
	if (!s.count(a[5]))
		s.insert(a[5]);
	else
		return;

	a[0] = 38 - 15 - a[1];
	if (!s.count(a[0]) && 1 <= a[0] && a[0] <= 19)
		s.insert(a[0]);
	else
		return;

	a[6] = 38 - a[0] - a[2];
	if (!s.count(a[6]) && 1 <= a[6] && a[6] <= 19)
		s.insert(a[6]);
	else
		return;

	a[7] = 38 - a[2] - a[3];
	if (!s.count(a[7]) && 1 <= a[7] && a[7] <= 19)
		s.insert(a[7]);
	else
		return;

	a[8] = 38 - a[3] - a[4];
	if (!s.count(a[8]) && 1 <= a[8] && a[8] <= 19)
		s.insert(a[8]);
	else
		return;

	a[9] = 38 - 10 - a[4];
	if (!s.count(a[9]) && 1 <= a[9] && a[9] <= 19)
		s.insert(a[9]);
	else
		return;

	a[10] = 38 - a[1] - a[5] - a[9];
	if (!s.count(a[10]) && 1 <= a[10] && a[10] <= 19)
		s.insert(a[10]);
	else
		return;

	a[11] = 38 - 13 - a[6] - a[10];
	if (!s.count(a[11]) && 1 <= a[11] && a[11] <= 19)
		s.insert(a[11]);
	else
		return;

	a[12] = 38 - a[1] - a[11] - a[7];
	if (!s.count(a[12]) && 1 <= a[12] && a[12] <= 19)
		s.insert(a[12]);
	else
		return;

	a[13] = 38 - a[6] - a[12] - a[8];
	if (!s.count(a[13]) && 1 <= a[13] && a[13] <= 19)
		s.insert(a[13]);
	else
		return;

	a[14] = 38 - a[7] - a[13] - a[9];
	if (!s.count(a[14]) && 1 <= a[14] && a[14] <= 19)
		s.insert(a[14]);
	else
		return;

	a[15] = 38 - a[0] - a[11] - a[14] - a[4];
	if (!s.count(a[15]) && 1 <= a[15] && a[15] <= 19)
		s.insert(a[15]);
	else
		return;

	cout  <<  a[0] << ' ' <<  a[11] << ' ' <<  a[15] << ' ' <<  a[14] << ' ' <<  a[4]  <<  endl;
}

int  main() {
	for (  a[1]  = 1  ;  a[1] <= 19  ;  a[1]++)
		for (  a[2]  = 1  ;  a[2] <= 19  ;  a[2]++)
			for (  a[3]  = 1  ;  a[3] <= 19  ;  a[3]++)
				for (  a[4]  = 1  ;  a[4] <= 19  ;  a[4]++)
					for (  a[5]  = 1  ;  a[5] <= 19  ;  a[5]++) {
						tiaojian();
					}

	return  0;
}

还不会dfs 就这样吧…
(gxnu202212303045实名上网)

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值