//第五届蓝桥杯软件类国赛真题-C-A-2_六角幻方
/*【题目】
标题:六角幻方
把 1 2 3 ... 19 共19个整数排列成六角形状,如下:
* * *
* * * *
* * * * *
* * * *
* * *
要求每个直线上的数字之和必须相等。共有15条直线哦!
再给点线索吧!我们预先填好了2个数字,第一行的头两个数字是:15 13,
参见图【p1.png】,黄色一行为所求。
请你填写出中间一行的5个数字。数字间用空格分开。
这是一行用空格分开的整数,请通过浏览器提交答案,
不要填写任何多余的内容(比如说明性的文字等)
*/
/*【解题思路】
解法一:深度优先搜索,且逐步搜索时,逐步判断,降低算法时间复杂度
答案:9 6 5 2 16
*/
#include<iostream>
using namespace std;
bool visit[19] = {false};//此变量用于标记17个未知圆圈上的数字是否已被访问过
int a[17] = {0};//此变量用于表示17个未知圆圈上的数字
/*
* @简介:深度优先搜索算法,搜索17个未知圆圈上的数字该填什么才符合题目条件
* @参数:currentStep表示当前搜索到了第几个圆圈
* @返回:无
*/
void dfs(int currentStep)
{
if(currentStep == 5)//当前已经搜索完第5个圆圈了,即搜索完a[0]~a[4]
{
if(15+13+a[0] != a[1]+a[2]+a[3]+a[4])//是否符合题目条件:每个直线上的数字之和必须相等
return; //不符合则return
}
if(currentStep == 6)//当前已经搜索完第6个圆圈了,即搜索完a[0]~a[5]
{
if(15+13+a[0] != 15+a[1]+a[5])
return;
}
if(currentStep == 10)
{
if(15+13+a[0] != a[5]+a[6]+a[7]+a[8]+a[9])
return;
else if(15+13+a[0] != a[0]+a[4]+a[9])
return;
}
if(currentStep == 11)
{
if(15+13+a[0] != 13+a[2]+a[6]+a[10])
return;
}
if(currentStep == 14)
{
if(15+13+a[0] != a[10]+a[11]+a[12]+a[13])
return;
else if(15+13+a[0] != 13+a[3]+a[8]+a[13])
return;
}
if(currentStep == 15)
{
if(15+13+a[0] != a[5]+a[10]+a[14])
return;
else if(15+13+a[0] != a[0]+a[3]+a[7]+a[11]+a[14])
return;
}
if(currentStep == 16)
{
if(15+13+a[0] != a[1]+a[6]+a[11]+a[15])
return;
else if(15+13+a[0] != a[4]+a[8]+a[12]+a[15])
return;
}
if(currentStep == 17)
{
if(15+13+a[0] != a[14]+a[15]+a[16])
return;
else if(15+13+a[0] != 15+a[2]+a[7]+a[12]+a[16])
return;
else if(15+13+a[0] != a[9]+a[13]+a[16])
return;
else
{
for(int i=0;i<17;i++)
cout<<a[i]<<" ";
cout<<endl;
}
}
else
{
for(int i=0;i<19;i++)//遍历数组visit[],查看1~19哪些数字被用过哪些数字没被用过
{
if(!visit[i])//如果没被用过,表示该数字可填写在当前圆圈中
{
a[currentStep] = i+1;//将该数字填写在当前圆圈中
visit[i] = true;//将该数字标记为被用过
dfs(currentStep+1);//进行下一个圆圈的填数步骤
visit[i] = false;//将该数字标记为未被用过,即返回,方便其它子树搜索使用
}
}
}
}
int main()
{
visit[12] = visit[14] = true;//visit[12]、visit[14]分别表示数字13、15,
//已经填写在第一二个圈里了,故标记为true,表示被用过
dfs(0);
return 0;
}