题目描述
幻方是一种很神奇的 NN 矩阵: 它由数字 1, 2, 3, ……, NN 构成, 且每行、每列及两条对角线上的数字之和都相同.
当 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*N 的幻方. 相邻两个整数之间用单个空格隔开.
输入样例
3
输出样例
8 1 6
3 5 7
4 9 2
Explanation
Source Code
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
typedef long long lli;
const int maxn = 40, maxm = maxn * maxn;
int n;
int arr[maxn][maxn];
int pos[maxm][2];
void setpos(int x, int y, int val)
{
arr[y][x] = val;
pos[val][0] = x;
pos[val][1] = y;
return ;
}
int main(int argc, char** argv)
{
scanf("%d", &n);
setpos((n + 1) / 2, 1, 1);
for (int k = 2; k <= n * n; k++) {
if (pos[k - 1][1] == 1 && pos[k - 1][0] != n)
setpos(pos[k - 1][0] + 1, n, k);
else if (pos[k - 1][0] == n && pos[k - 1][1] != 1)
setpos(1, pos[k - 1][1] - 1, k);
else if (pos[k - 1][0] == n && pos[k - 1][1] == 1)
setpos(n, 2, k);
else {
int x = pos[k - 1][0],
y = pos[k - 1][1];
if (!arr[y - 1][x + 1])
setpos(x + 1, y - 1, k);
else
setpos(x, y + 1, k);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
return 0;
}