[蓝桥杯2015决赛]四阶幻方
题目描述
把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
就可以算为两种不同的方案。
分析
第一眼以为还是全排列,但是仔细一看16!挂机到赛后可能都跑不出来,只能dfs+剪枝了。这里采用一维数组来模拟二维数组的排列,跑起来还是蛮快的。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int n;
int a[20];
bool st[20];
bool used[20];
int ans;
void dfs(int u)
{
if(u > n ){
if(a[13] + a[14] + a[15] + a[16] != 34) return;
if(a[4] + a[8] + a[12] + a[16] != 34) return ;
if(a[1] + a[6] + a[11] + a[16] != 34) return ;
ans ++;
return ;
}
if(u > 4){
if(a[1] + a[2] + a[3] + a[4] != 34) return;
}
if(u > 13){
if(a[4] + a[7] + a[10] + a[13] != 34) return ;
if(a[1] + a[5] + a[9] + a[13] != 34) return;
}
if(u > 14){
if(a[2] + a[6] + a[10] + a[14] != 34) return;
}
if(u > 15){
if(a[3] + a[7] + a[11] + a[15] != 34) return;
}
if(u > 8){
if(a[5] + a[6] + a[7] + a[8] != 34) return;
}
if(u > 12){
if(a[9] + a[10] + a[11] + a[12] != 34) return;
}
for(int i = 2; i <= n; i ++ ){
if(!used[i]){
a[u] = i;
used[i] = true;
dfs(u + 1);
used[i] = false;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
n = 16;
a[1] = 1;
used[1] = true;
dfs(2);
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号