题目描述

幻方是一种很神奇的 NN 矩阵: 它由数字 1, 2, 3, ……, NN 构成, 且每行、每列及两条对角线上的数字之和都相同.

当 N 为奇数时, 我们可以通过以下方法构建一个幻方:

首先将 1 写在第一行的中间.

之后, 按如下方式从小到大依次填写每个数 K (K=2, 3, …, N*N):

  1. 若 (K−1) 在第一行但不在最后一列, 则将 K 填在最后一行, (K−1) 所在列的右一列;
  2. 若 (K−1) 在最后一列但不在第一行, 则将 K 填在第一列, (K−1) 所在行的上一行;
  3. 若 (K−1) 在第一行最后一列, 则将 K 填在 (K−1) 的正下方;
  4. 若 (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;
}