题意:把1~16的数字填入4x4的方格中,使得行、列以及两个对角线的和都相等,若左上角为定值1,计算一共有多少种排列方案
分析:先填充(要顺便剪枝~),然后判断是否合理~
比如这样~ 行列主副对角线和都为34~
1 2 15 16
12 14 3 5
13 7 10 4
8 11 6 9
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(a,b) memset(a,b,sizeof(a))
const ll maxn=1e6+10;
int ans=0;
int book[20];
int a[10][10];
bool row(int x) {///检查行
int cnt=0;
for(int i=0; i<4; i++) {
cnt+=a[x][i];
}
if(cnt!=34)return false;
return true;
}
bool col(int x) {///检查列
int cnt=0;
for(int i=0; i<4; i++) {
cnt+=a[i][x];
}
if(cnt!=34)return false;
return true;
}
bool check() {
int ans1=a[0][0]+a[1][1]+a[2][2]+a[3][3];///主对角
if(ans1!=34)return false;
ans1=a[0][3]+a[1][2]+a[2][1]+a[3][0];///副对角
if(ans1!=34)return false;
for(int i=0; i<4; i++) {///行
if(!row(i))
return false;
}
for(int i=0; i<4; i++) {///列
if(!col(i))
return false;
}
return true;/// 合理排序
}
void dfs(int n) {
if(n==16) {
if(check()) {
ans++;
}
return;///返回上一层!
}
if(n%4==0) { ///剪枝 很重要
if(!row(n/4-1))
return ;
}
for(int i=2; i<=16; i++) {
if(book[i]==0) {
a[n/4][n%4]=i;///为此时的位置填充值
book[i]=1;///标记
dfs(n+1);
book[i]=0;///回溯
}
}
}
int main() {
a[0][0]=1;
dfs(1);///第一个值确定
cout<<ans<<endl;
return 0;
}