题目描述:
把1~16的数字填入4x4的方格中,使得行、列以及两个对角线的和都相等,满足这样的特征时称为:四阶幻方。
四阶幻方可能有很多方案。如果固定左上角为1,请计算一共有多少种方案。
比如:
1 2 15 16
12 14 3 5
13 7 10 4
8 11 6 9
以及:
1 12 13 8
2 14 7 11
15 3 10 6
16 5 4 9
就可以算为两种不同的方案。
请提交左上角固定为1时的所有方案数字,不要填写任何多余内容或说明文字。
分析:
刚开始没有想那么多,没有想那么多,以为和上一题一样,弄个数组的全排列就可以了,于是...
#include<iostream>
#include<algorithm>
using namespace std;
int a[15]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int sum=0;
int check();
int main()
{
do
{
if(check())
{
for(int i=0;i<15;i++)
cout<<a[i]<<" ";
cout<<endl;
sum++;
}
}while(next_permutation(a,a+15));
cout<<sum;
return 0;
}
int check()
{
int he=1+a[0]+a[1]+a[2];
if(he!=(a[4]+a[5]+a[6]+a[7])) return 0;
if(he!=(a[8]+a[9]+a[10]+a[11])) return 0;
if(he!=(a[12]+a[13]+a[14]+a[15])) return 0;
if(he!=(1+a[4]+a[8]+a[12])) return 0;
if(he!=(a[0]+a[5]+a[9]+a[13])) return 0;
if(he!=(a[1]+a[6]+a[10]+a[14])) return 0;
if(he!=(a[2]+a[7]+a[11]+a[15])) return 0;
if(he!=(1+a[5]+a[10]+a[15])) return 0;
if(he!=(a[2]+a[6]+a[9]+a[12])) return 0;
return 1;
}
不出意外地,跑了十几分钟也没跑出来,简单按了下计算器,已经达到万亿级别了....15!=1 307 674 368 000,没办法,只好换方法了,那就用DFS吧,可是DFS跑了很久也跑不出来,博主生气了,就去网上查,看看各路大神是怎么写的,结果发现大家基本也都用DFS?????
博主更加生气了,凭什么你的DFS可以跑出来,我的就不行?
仔细一看,我是凑够八个数,才开始判断是否符合条件,但人家从四个数就开始判断是否符合条件,我:??????,四个数怎么判断?或许有某个规律在里面?查了查确实是,像这道题,每行之和必定为34.好吧,要是从第四个数就开始判断是否==34,那确实是一个很强大的剪枝函数,一下子减掉了好多没用的东西,于是,大概20多秒,出了结果:
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int b[15]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int a[15];
int book[15];
void DFS(int k);
int sum=0;
int check(int temp);
int main()
{
for(int i=0;i<15;i++)
{
a[i]=0;
book[i]=0;
}
DFS(0);
cout<<sum;
return 0;
}
void DFS(int k)
{
if(k==3)
{
if(!check(k-1))
return;
}
else if(k==7)
{
if(!check(k-1))
return;
}
else if(k==11)
{
if(!check(k-1))
return;
}
else if(k==12)
{
if(!check(k-1))
return;
}
else if(k==13)
{
if(!check(k-1))
return;
}
else if(k==14)
{
if(!check(k-1))
return;
}
else if(k==15)
{
if(check(k-1))
{
sum++;
return;
}
else
return;
}
for(int i=0;i<15;i++)
{
if(book[i]==0)
{
a[k]=b[i];
book[i]=1;
/*
cout<<k<<endl;
cout<<"a[15] is: "<<endl;
for(int i=0;i<15;i++)
cout<<a[i]<<" ";
cout<<endl;
*/
DFS(k+1);
book[i]=0;
a[k]=0;
}
}
}
int check(int temp)
{
int he=1+a[0]+a[1]+a[2];
if(he!=34)
return 0;
int flag=0;
if(temp==6)
{
if(he==(a[3]+a[4]+a[5]+a[6]))
flag=1;
return flag;
}
else if(temp==10)
{
if(he==(a[7]+a[8]+a[9]+a[10]))
flag=1;
}
else if(temp==11)
{
if(he==(1+a[3]+a[7]+a[11]))
if(he==(a[2]+a[5]+a[8]+a[11]))
flag=1;
return flag;
}
else if(temp==12)
{
if(he==(a[0]+a[4]+a[8]+a[12]))
flag=1;
return flag;
}
else if(temp==13)
{
if(he==(a[1]+a[5]+a[9]+a[13]))
flag=1;
return flag;
}
else if(temp==14)
{
if(he==(a[11]+a[12]+a[13]+a[14]))
if(he==(a[2]+a[6]+a[10]+a[14]))
if(he==(1+a[4]+a[9]+a[14]))
flag=1;
return flag;
}
}
答案:
416