洛谷题单-数组-P2615-神奇的幻方(C语言)题解

题目描述

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

当 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

方法一:暴力模拟,按照题目要求判断,代码及注释如下:

#include<stdio.h>

int matrix[40][40]; //定义一个全局二维数组,数组中每个元素初始化为0
int main()
{
    int n = 0;
    scanf("%d",&n); //输入数字n
    int x = 0,y = n / 2;    //x、y分别表示k所处的位置
    matrix[x][y] = 1;   //k=1时 1默认在第一行中间 本题不考虑输入偶数的情况

    for(int k = 2;k <= n * n;k++)   //从k=2开始,按照题目要求判断
    {
        if(x == 0 && y != n-1)  //第一种情况
        {
            x = n - 1;
            y += 1;
        }
        else if(x != 0 && y == n-1) //第二种情况
        {
            x -= 1;
            y = 0;
        }
        else if(x == 0 && y == n-1) //第三种情况
        {
            x += 1;
        }
        else if(x != 0 && y != n-1) //第四种情况
        {
            if(matrix[x-1][y+1] == 0)   //如果此时右上角没数,则填在右上角
            {
                x -= 1;
                y += 1;
            }
            else    //若右上角有数,则填在正下方
            {
                x += 1;
            }
        }
        matrix[x][y] = k;   //判断完毕后将k放到x、y的位置上
    }

    for(int i = 0;i < n;i++)    //将幻方打印输出
    {
        for(int j = 0;j < n;j++)
        {
            printf("%d ",matrix[i][j]);
        }
        printf("\n");
    }
    return 0;
}

 方法二(看了一些题解后发现):

幻方规律:从第一行中间放置1后,后一个数字都是放在前一个数字的右上方,若那个位置已经有数字,则放在这个数字的正下方(注意是否越界,第一行数字的右上方在最后一行,最后一列数字的右上方在第一列)

下面是代码及注释:

#include<stdio.h>

int matrix[40][40]; //定义一个全局二维数组,数组中每个元素初始化为0
int main()
{
    int n = 0;
    scanf("%d",&n); //输入数字n
    int x = 0,y = n / 2;    //x、y分别表示k所处的位置
    matrix[x][y] = 1;   //k=1时 1默认在第一行中间 本题不考虑输入偶数的情况

    for(int k = 2;k <= n * n;k++)   //从k=2开始遍历到n*n结束
    {
        int xx = x,yy = y;  //记录当前位置下标,方便右上角有数时返回上一步定位正下方的操作
        x--;
        if(x < 0) x = n-1;    
        //若行越界(当前数字位于第一行,注意我们所说的矩阵中的第一行为二维数组中的第0行),
        //则应置于最后一行
        y++;
        if(y > (n-1)) y = 0;    
        //若列越界(当前数字位于最后一列,注意我们所说的最后一列为二维数组中的第n-1列,
        //因为有第0列),则应置于第一列

        //以上x++ 和 y-- 两行语句完成了往右上角移动的操作

        if(matrix[x][y] != 0)   
        //如果右上角有数字(因为此时x、y已经进行了向右上角移动的操作,
        //所以需要通过xx、yy来定位当前数字的正下方)
        {
            x = xx + 1;
            y = yy;
        }

        matrix[x][y] = k;    //将k放到判断好后的位置
    }

    for(int i = 0;i < n;i++)    //将幻方打印输出
    {
        for(int j = 0;j < n;j++)
        {
            printf("%d ",matrix[i][j]);
        }
        printf("\n");
    }

    return 0;
}

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值