ZZULIOJ:1203: 做幻方

看到以前学校的大佬写的代码,真心觉得很nb,本蒟蒻稍微加了亿点注释,方便大家看得懂。

第一次发博客排版不怎么样,各位佬别在意

题目描述

Apple最近迷上了做幻方,Apple还是个中高手,只要你说个奇数N就能把N*N的幻方做出来。其实你可以比他做得更好的。Apple总是画得很乱,而你可以利用程序排得很整齐^_^ 幻方的要求:每一行,每一列,还有两条斜线上数字的和都相等.

输入

每行一个奇数N(0< N < 30),输入0结束

输出

输入一个奇数,输出一个幻方,顺序参照样板输出;同一列的数右对齐,数与数用一个空格分开;输出完以后加一个回车。

样例输入

5
1
0

样例输出

11 18 25  2  9
10 12 19 21  3
 4  6 13 20 22
23  5  7 14 16
17 24  1  8 15

1
// 解奇阶幻方的通用模块
/* 奇数阶幻方
最经典的填法是罗伯特法(楼梯法),填写方法是这样:
把1(或最小的数)放在第一行正中;按以下规律排列剩下的n×n-1个数:
(1)每一个数放在前一个数的右上一格;
(2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,
仍然要放在右一列;
(3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,
仍然要放在上一行;
(4)如果这个数所要放的格已经超出了顶行且超出了最右列,
那么就把它放在前一个数的下一行同一列的格内;
(5)如果这个数所要放的格已经有数填入,处理方法同(4)。
这种写法总是先向“右上”的方向,象是在爬楼梯。
三阶幻方:
   8   1   6
   3   5   7
   4   9   2    */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int sort(int n);

int main()
{
    int n;
    while (scanf("%d", &n), n != 0)
        sort(n);    // n 为阶数
    return 0;
}

int sort(int n)
{
    int i, x = 0, y = 0, j;
    int(*a)[n] = (int(*)[n])malloc(sizeof(int) * n * n);   // 申请动态二维数组  在这里也可以 a[n][n](直到 C99 才支持)
    x = n / 2; // 指向中间列
    y = 0;
    for (i = 1; i <= n * n; i++)
    {
        a[y][x] = i;     // 把 1 (或最小的数)放在第一行正中
        if (i % n == 0)  //  每放 n 个后,下一个一定是已经填过的格子
            y++;         // 需要在下一行继续放
        else
            x++, y--;        // 向右上方移动
        x = x % n;           //  当 x 在最右方还需要右移的时候,把 x初始化为 1
        y = (y % n + n) % n; // 当 y 在最上方,且还需要向右上移动时,y--后 y = -1,需要把 y 变为n - 1, 当 y 在最下方时还需要向下移时, 作用等同于 y = y % n
    }

    int fmt = log10(n * n); // 取位数, 按照要求输出,数字之间留出空格 
    if (fmt == 0)  //  fmt -> format   由于30*30 = 900最大为3位数,故下面只列举了3种情况
    {
        for (i = n - 1; i >= 0; i--)  //  题目格式刚好上下反转了一下
        {
            for (j = 0; j < n - 1; j++) // 左右并没有反转
            {
                printf("%d ", a[i][j]);
            }
            printf("%d", a[i][n - 1]); // 每行最后一个不输出空格
            printf("\n");
        }
    }
    else if (fmt == 1)
    {
        for (i = n - 1; i >= 0; i--)
        {
            for (j = 0; j < n - 1; j++)
            {
                printf("%2d ", a[i][j]);
            }
            printf("%2d", a[i][n - 1]);
            printf("\n");
        }
    }
    else if (fmt == 2)
    {
        for (i = n - 1; i >= 0; i--)
        {
            for (j = 0; j < n - 1; j++)
            {
                printf("%3d ", a[i][j]);
            }
            printf("%3d", a[i][n - 1]);
            printf("\n");
        }
    }
    free(a);   //  申请的空间用后释放    如果上方用的是a[n][n],就不用写 free了(如果写了程序会异常结束)
    printf("\n");  //  按照题目要求,每组数据直接要有一个换行符隔开
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.Zero

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值