标题:六角幻方
把 1 2 3 ... 19 共19个整数排列成六角形状,如下:
* * *
* * * *
* * * * *
* * * *
* * *
要求每个直线上的数字之和必须相等。共有15条直线哦!
再给点线索吧!我们预先填好了2个数字,第一行的头两个数字是:15 13,参见图【p1.png】,黄色一行为所求。
请你填写出中间一行的5个数字。数字间用空格分开。
这是一行用空格分开的整数,请通过浏览器提交答案,不要填写任何多余的内容(比如说明性的文字等)
分析:应该是一道DFS的题目,注意要进行剪枝。
比如当填到第8个数时,前面7个数,也就是第一二行的数字就确定了,这时可以先判断第一行的数字之和和第二行数字之和是否相等,若不相等,这说明已经没必要继续下去。
需要注意的就是哪些情况下会确定一条直线上的数,这种情况都进行判断。
我这里a数组从1到19表示所填的数,用变量x表示当前填数个数,从3开始,到20结束。
#include <stdio.h>
using namespace std;
int num[20];//存放数字0-19
int a[20]= {0}; //存放答案
int vis[20]= {0}; //标记每位数字是否已经存在
void dfs(int x)//x表示当前填数个数
{
if(x==8)
{
if(28+a[3]!=a[4]+a[5]+a[6]+a[7])
return;
}
if(x==9)
{
if(15+a[4]+a[8]!=28+a[3])
return;
}
if(x==13)
{
if(a[8]+a[9]+a[10]+a[11]+a[12]!=28+a[3])
return;
if(a[3]+a[7]+a[12]!=28+a[3])
return;
}
if(x==14)
{
if(28+a[3]!=13+a[5]+a[9]+a[13])
return;
}
if(x==17)
{
if(13+a[6]+a[11]+a[16]!=28+a[3]||a[13]+a[14]+a[15]+a[16]!=28+a[3])
return;
}
if(x==18)
{
if(a[3]+a[6]+a[10]+a[14]+a[17]!=28+a[3]||a[8]+a[13]+a[17]!=28+a[3])
return;
}
if(x==19)
{
if(a[7]+a[11]+a[15]+a[18]!=28+a[3]||a[4]+a[9]+a[14]+a[18]!=28+a[3])
return;
}
if(x==20)
{
if(a[17]+a[18]+a[19]==28+a[3])
{
printf("%d %d %d %d %d",a[8],a[9],a[10],a[11],a[12]);
return;
}
}
for(int i=1; i<20; i++)
{
if(!vis[i])
{
vis[i]=1;
a[x]=num[i];
dfs(x+1);
vis[i]=0;
}
}
}
int main()
{
for(int i=0; i<=19; i++)
num[i]=i;
a[1]=15;
a[2]=13;
vis[13]=vis[15]=1;
dfs(3);
// for(int i=1; i<=19; i++)
// printf("%d ",a[i]);
return 0;
}
关于六角幻方,理论上只有一种解法: