四阶幻方

把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 <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int s[16],c;
bool vis[17];

bool check(int k) {
    int a = k / 4,b = k % 4;
    if(a == 2 && vis[34 - (s[b] + s[b + 4] + s[b + 8])]) return false;
    if(a == 3 && s[b] + s[b + 4] + s[b + 8] + s[b + 12] != 34) return false;
    a *= 4;
    if(b == 2 && vis[34 - (s[a] + s[a + 1] + s[a + 2])]) return false;
    if(b == 3 && s[a] + s[a + 1] + s[a + 2] + s[a + 3] != 34) return false;
    if(k == 9 && vis[34 - (s[3] + s[6] + s[9])]) return false;
    if(k == 10 && vis[34 - (s[0] + s[5] + s[10])]) return false;
    if(k == 12 && s[3] + s[6] + s[9] + s[12] != 34) return false;
    if(k == 15 && s[0] + s[5] + s[10] + s[15] != 34) return false;
    return true;
}
void dfs(int k) {
    if(k >= 16) {
        c ++;
        return;
    }
    for(int i = 2;i <= 16;i ++) {
        if(!vis[i]) {
            vis[i] = true;
            s[k] = i;
            if(check(k)) dfs(k + 1);
            s[k] = 0;
            vis[i] = false;
        }
    }
}
int main() {
    s[0] = 1;
    dfs(1);
    printf("%d",c);
}
原文地址:https://www.cnblogs.com/8023spz/p/10640042.html