描述
幻方是一种很神奇的 N×N 矩阵:它由数字 1,2,3,…,N×N 构成,且每行、每列及两条对角线上的数字之和都相同。
当 N 为奇数时,我们可以通过以下方法构建一个幻方:
首先将 1 写在第一行的中间。
之后,按如下方式从小到大依次填写每个数 K(K=2,3,…,N×N):
若 (K - 1) 在第一行但不在最后一列,则将 K 填在最后一行, (K - 1) 所在列的右一列;
若 (K - 1) 在最后一列但不在第一行,则将 K 填在第一列, (K - 1) 所在行的上一行;
若 (K - 1) 在第一行最后一列,则将 K 填在 (K - 1) 的正下方;
若 (K - 1) 既不在第一行,也不在最后一列,如果 (K - 1) 的右上方还未填数,则将 K 填在 (K - 1) 的右上方,否则将 K 填在 (K - 1) 的正下方。
现给定 N ,请按上述方法构造 N×N 的幻方。
输入描述
输入只有一行,包含一个整数,即幻方的大小
输出描述
输出包含 N 行,每行 N 个整数,即按上述方法构造出的 N×N 的幻方。相邻两个整数之间用单个空格隔开。
用例输入
3
用例输出
8 1 6 3 5 7 4 9 2
提示
对于 100% 的数据, 1≤N≤39 且为奇数。
思路:
我们先来看一下用例:
假设未填数都是0
1.将1填在第一行的中间:
0 1 0
0 0 0
0 0 0
2.因为 1 在第一行但不在最后一列,所以将2填在最后一行,1所在列的右一列:
0 1 0
0 0 0
0 0 2
3.因为 2 在最后一列但不在第一行,所以将3填在第一列,2所在行的上一行:
0 1 0
3 0 0
0 0 2
4.因为 3 既不在第一行,也不在最后一列,3的右上方已经填数,所以将4填在3的正下方:
0 1 0
3 0 0
4 0 2
5.因为 4 既不在第一行,也不在最后一列,4的右上方还未填数,所以将5填在4的右上方:
0 1 0
3 5 0
4 0 2
6.因为 5 既不在第一行,也不在最后一列,5的右上方还未填数,所以将6填在5的右上方:
0 1 6
3 5 0
4 0 2
7.因为 6 在第一行最后一列,所以将7填在6的正下方:
0 1 6
3 5 7
4 0 2
8.因为 7 在最后一列但不在第一行,所以将8填在第一列,7所在行的上一行:
8 1 6
3 5 7
4 0 2
9.因为 8 在第一行但不在最后一列,所以将9填在最后一行,8所在列的右一列:
8 1 6
3 5 7
4 9 2
幻方完成!
由此,我们可以推出代码:
#include<bits/stdc++.h>
using namespace std;
int li[40][40]={0};
int main()
{
int n;
cin>>n;
li[0][n/2]=1;
int h=0,l=n/2;
for (int i=2;i<=n*n;i++)
{
if (h==0 && l!=n-1)
{
li[n-1][l+1]=i;
h=n-1,l++;
}
else if (l==n-1 && h!=0)
{
li[h-1][0]=i;
l=0,h--;
}
else if (h==0 && l==n-1)
{
li[1][n-1]=i;
h++;
}
else if (h!=0 && l!=n-1)
{
if (li[h-1][l+1]==0)
{
li[h-1][l+1]=i;
h--,l++;
}
else
{
li[h+1][l]=i;
h++;
}
}
}
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++) cout<<li[i][j]<<" ";
cout<<endl;
}
}