题目描述
给一个 n×n 的方格矩阵,还有 n×n 个整数,让你将这些整数填入矩阵,使得每行每列每个对角线上整数的和都相等。下面给出几个例子:
输入格式
第一行一个整数 n (1≤n≤4)。
第二行n×n 个整数 (−108≤ai≤108)。
输出格式
第一行一个整数 s 代表每行每列每个对角线的和值。
接下来输出一个 n×n 的矩阵,表示填数方案。
数据保证有解,可能存在多种方案,输出字典序最小的(将每行顺次相连之后,字典序最小)
输入输出样例
输入
3 1 2 3 4 5 6 7 8 9
输出
15 2 7 6 9 5 1 4 3 8
说明/提示
数据范围及约定
对于80% 的数据,保证 1≤n≤3;
对于100% 的数据,保证 1≤n≤4。
注意
方法是dfs
剪枝:填到每一行、每一列最后一个数字时判断是否合法,速度能快很多
输出时要输出字典序最小的,所以一开始要把输入数据排序。
#include<bits/stdc++.h>
using namespace std;
int n,a[101],z=0,f[101],ans[11][11];
void s(int x,int y){
if(x==n&&y==n+1){//找到目标解,输出
cout<<z<<endl;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(j==n) cout<<ans[i][j]<<endl; else cout<<ans[i][j]<<" ";
exit(0);//直接结束程序
}
if(y>n){//下一行
s(x+1,1);
return;
}
for(int i=1;i<=n*n;i++)if(f[i]==0){//未使用
if(y==n){//行判断
int u=a[i];
for(int j=1;j<n;j++) u+=ans[x][j];
if(u!=z) continue;
}
if(x==n){//列判断
int u=a[i];
for(int j=1;j<n;j++) u+=ans[j][y];
if(u!=z) continue;
}
if(x==n&&y==1){//斜线(右上角到左下角)
int u=a[i];
for(int j=1;j<n;j++) u+=ans[j][n-j+1];
if(u!=z) continue;
}
if(x==n&&y==n){//斜线(左上角到右下角)
int u=a[i];
for(int j=1;j<n;j++) u+=ans[j][j];
if(u!=z) continue;
}
f[i]=1;
ans[x][y]=a[i];
//标记
s(x,y+1);
f[i]=0;
//清除标记
}
}
int main(){
cin>>n;
for(int i=1;i<=n*n;i++) cin>>a[i],z+=a[i];
z/=n;//算出每行每列每个对角线上的整数
sort(a+1,a+n*n+1);//sort快排
s(1,1);
return 0;
}
嘿嘿,我的代码风格就总变,今天想这么写,明天想那么写······