1、四阶幻方
把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
就可以算为两种不同的方案。
#include <iostream>
#include <cstring>
using namespace std;
int a[17];
int b[17];
void dfs(int step);
int sum=0;
int main()
{
memset(b,1,sizeof(b));
a[1]=1;
b[1]=0;
dfs(2);
cout<<sum;
}
void dfs(int step)
{
if(step==5)
{
int x=a[1]+a[2]+a[3]+a[4];
if(x!=34)
return;
}
else if(step==9)
{
int x=a[5]+a[6]+a[7]+a[8];
if(x!=34)
return;
}
else if(step==11)
{
int x=a[4]+a[7]+a[10];
if(b[34-x]!=1)
return;
a[13]=34-x;
}
else if(step==12)
{
int x=a[1]+a[6]+a[11];
if(b[34-x]!=1)
return;
a[16]=34-x;
}
else if(step==13)
{
int x=a[9]+a[10]+a[11]+a[12];
if(x!=34)
return;
}
else if(step==14)
{
int x=a[1]+a[5]+a[9]+a[13];
if(x!=34)
return;
}
else if(step==15)
{
int x=a[2]+a[6]+a[10]+a[14];
if(x!=34)
return;
}
else if(step==16)
{
int x=a[3]+a[7]+a[11]+a[15];
if(x!=34)
return;
}
else if(step==17)
{
int x=a[1]+a[6]+a[11]+a[16];
int y=a[4]+a[7]+a[10]+a[13];
if(x!=34)
return;
if(y!=34)
return;
sum++;
return;
}
for(int i=2;i<=16;i++)
if(b[i])
{
b[i]=0;
a[step]=i;
dfs(step+1);
b[i]=1;
}
}
2、反幻方
我国古籍很早就记载着
2 9 4
7 5 3
6 1 8
这是一个三阶幻方。每行每列以及对角线上的数字相加都相等。
下面考虑一个相反的问题。
可不可以用 1~9 的数字填入九宫格,使得:每行每列每个对角线上的数字和都互不相等呢?
这应该能做到。
比如:
9 1 2
8 4 3
7 5 6
你的任务是搜索所有的三阶反幻方。并统计出一共有多少种。旋转或镜像算同一种。
比如:
9 1 2
8 4 3
7 5 6
7 8 9
5 4 1
6 3 2
2 1 9
3 4 8
6 5 7
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
int a[9]={1,2,3,4,5,6,7,8,9};
int main()
{
int ans=0;
do{
int b[8];
b[0]=a[0]+a[1]+a[2];
b[1]=a[3]+a[4]+a[5];
b[2]=a[6]+a[7]+a[8];
b[3]=a[0]+a[3]+a[6];
b[4]=a[1]+a[4]+a[7];
b[5]=a[2]+a[5]+a[8];
b[6]=a[0]+a[4]+a[8];
b[7]=a[2]+a[4]+a[6];
set < int > tem;
for(int i=0;i<8;i++)
tem.insert(b[i]);
if(tem.size()==8)
ans++;
}while(next_permutation(a,a+9));
cout<<ans/8;
}
next_permutation(a,a+9)全排列函数
https://www.cnblogs.com/weixq351/p/9497108.html
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
int n;
while(scanf("%d",&n)&&n){
int a[1000];
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
do{
for(int i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}while(next_permutation(a,a+n));
}
return 0;
}
例如输入
3
1 0 2
如果有sort()
输出为
0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0
若无
则输出为
1 0 2
1 2 0
2 0 1
2 1 0
发现函数next_permutation()是按照字典序产生排列的,并且是从数组中当前的字典序开始依次增大直至到最大字典序