六角幻方暴力填数
题目就是上面图了 感兴趣自己搜一下原题
几何推理:
已知所有数的范围是从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实名上网)