魔方阵

编写程序,实现如下表所示的5-魔方阵。
17241815
23571416
46132022
101219213
11182529
5-魔方阵

问题分析

所谓“n-魔方阵”,指的是使用1〜n2共n2个自然数排列成一个n×n的方阵,其中n为奇数;该方阵的每行、每列及对角线元素之和都相等,并为一个只与n有关的常数,该常数为n×(n2+1)/2。

例如5-魔方阵,其第一行、第一列及主对角线上各元素之和如下:
  • 第一行元素之和:17+24+1+8+15=65
  • 第一列元素之和:17+23+4+10+11=65
  • 主对角线上元素之和:17+5+13+21+9=65

而 n×(n2+1)/2=5×(52+1)/2=65 可以验证,5-魔方阵中其余各行、各列及副对角线上的元素之和也都为65。

假定阵列的行列下标都从0开始,则魔方阵的生成方法为:在第0行中间置1,对从2开始的其余n2-1个数依次按下列规则存放:
(1) 假定当前数的下标为(i,j),则下一个数的放置位置为当前位置的右上方,即下标为(i-1,j+1)的位置。
(2) 如果当前数在第0行,即i-1小于0,则将下一个数放在最后一行的下一列上,即下标为(n-1,j+1)的位置。
(3) 如果当前数在最后一列上,即j+1大于n-1,则将下一个数放在上一行的第一列上,即下标为(i-1,0)的位置。
(4) 如果当前数是n的倍数,则将下一个数直接放在当前位置的正下方,即下标为(i+1,j)的位置。

算法设计

在设计算法时釆用了下面一些方法:
  • 定义array()函数,array()函数的根据输入的n值,生成并显示一个魔方阵,当发现n不是奇数时,就加1使之成为奇数。
  • 使用动态内存分配与释放函数malloc()与free(),在程序执行过程中动态分配与释放内存,这样做的好处是使代码具有通用性,同时提高内存的使用率。

在分配内存时还要注意,由于一个整型数要占用两个内存,因此,如果魔方阵中要存放的数有max个,则分配内存时要分配2*max个单元,从而有malloc(max+max)。在malloc()函数中使用max+max而不是2*max是考虑了程序运行的性能。

显然应该使用二维数组来表示魔方阵,但虽然数组是二维形式的,而由于内存是一维线性的,因此在存取数组元素时,要将双下标转换为单个索引编号。在程序中直接定义了指针变量来指向数组空间,即使用malloc()函数分配的内存。

下面是完整的代码:

    
    
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int array(int n)
  4. {
  5. int i, j, no, num, max;
  6. int *mtrx;
  7. if(n%2 == 0) /*n是偶数,则加1使其变为奇数*/
  8. {
  9. n=n+1;
  10. }
  11. max=n*n;
  12. mtrx=(int *)malloc(max+max); /*为魔方阵分配内存*/
  13. mtrx[n/2]=1; /* 将1存入数组*/
  14. i=0; /*自然数1所在行*/
  15. j=n/2; /*自然数1所在列*/
  16. /*从2开始确定每个数的存放位置*/
  17. for(num=2; num<=max; num++)
  18. {
  19. i=i-1;
  20. j=j+1;
  21. if((num-1)%n == 0) /*当前数是n的倍数*/
  22. {
  23. i=i+2;
  24. j=j-1;
  25. }
  26. if(i<0) /*当前数在第0行*/
  27. {
  28. i=n-1;
  29. }
  30. if(j>n-1) /*当前数在最后一列,即n-1列*/
  31. {
  32. j=0;
  33. }
  34. no=i*n+j; /*找到当前数在数组中的存放位置*/
  35. mtrx[no]=num;
  36. }
  37. /*打印生成的魔方阵*/
  38. printf("生成的%d-魔方阵为:",n);
  39. no=0;
  40. for(i=0; i<n; i++)
  41. {
  42. printf("\n");
  43. for(j=0; j<n; j++)
  44. {
  45. printf("%3d", mtrx[no]);
  46. no++;
  47. }
  48. }
  49. printf("\n");
  50. free(mtrx);
  51. return 0;
  52. }
  53. int main()
  54. {
  55. int n;
  56. printf("请输入n值:\n");
  57. scanf("%d", &n);
  58. array(n); /*调用array函数*/
  59. return 0;
  60. }
运行结果:
请输入n值:
5↙︎
生成的5-魔方阵为:
17 24  1  8 15
23  5  7 14 16
 4  6 13 20 22
10 12 19 21  3
11 18 25  2  9

知识点补充

在解决该问题时,采用的是动态分配内存的方式,并使用了指针变量mtrx来指向二维数组中的元素。在算法设计中,要存储魔方阵需要一个二维数组,因此再给出直接使用二维数组来生成5-魔方阵的程序。

直接使用二维数组生成5-魔方阵的代码如下:

    
    
  1. #include<stdio.h>
  2. #define N 5
  3. int main()
  4. {
  5. int a[N][N]={0}, i, j, k, t, x, y;
  6. i=0; /*自然数1的行标*/
  7. j=N/2; /*自然数1的列标*/
  8. t=N-1; /*最后一行、最后一列的下标*/
  9. for(k=1; k<=N*N; k++)
  10. {
  11. a[i][j]=k;
  12. x=i;
  13. y=j;
  14. if(i == 0)
  15. i=t;
  16. else
  17. i=i-1;
  18. if(j != t)
  19. j=j+1;
  20. else
  21. j=0;
  22. if(a[i][j]!=0)
  23. {
  24. i=x+1;
  25. j=y;
  26. }
  27. }
  28. printf("生成的5-魔方阵为:");
  29. for(i=0; i<N; i++)
  30. {
  31. printf("\n");
  32. for(j=0; j<N; j++)
  33. {
  34. printf("%3d", a[i][j]);
  35. }
  36. }
  37. printf("\n");
  38. return 0;
  39. }
运行结果:
生成的5-魔方阵为:
17 24  1  8 15
23  5  7 14 16
 4  6 13 20 22
10 12 19 21  3
11 18 25  2  9
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值