当前位置:编程学习 > C/C++ >>

C语言编程

输出1~n*n的自然数构成的魔方阵
答案:#include <stdio.h> 
int main()
{
int n;
int a[31][31];
while(scanf("%d",&n)!=EOF)
{
int m=1;
int i=0;
int j=(n-1)/2;
while(m<=n*n)
{

a[i][j]=m;
m++;
i--;
j++;
if((m-1)%n==0&&m>1)
{
i=i+2;
j=j-1;
}
if(i<0) i=i+n;
if(j>(n-1)) j=j-n;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%4d",a[i][j]);
if(j==(n-1))
printf("\n");
}
}
}
return 0;
}(1)将1放在第一行中间一列;
  (2)从2开始直到n×n止各数依次按下列规则存放;每一个数存放的行比前一个数的行数减1,列数加1(例如上面的三阶魔方阵,5在4的上一行后一列);
  (3)如果上一个数的行数为1,则下一个数的行数为n(指最下一行);例如1在第一行,则2应放在最下一行,列数同样加1;
  (4)当上一个数的列数为n时,下一个数的列数应为1,行数减去1。例如2在第3行最后一列,则3应放在第二行第一列;
  (5)如果按上面规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。例如按上面的规定,4应该放在第1行第2列,但该位置已经被占据,所以4就放在3的下面;

 

经过我的总结,这个方法是比较好的,它避免的对魔方阵奇偶性的讨论。

首先把从1~n2的整数按从小到大的顺序排列成一个n×n的方阵A进行观察。(本文中所有n都是指大于1的奇数,下文中均以“A”代表这类顺序排列的n×n方阵)
以5阶阵为例:以下是A方阵
1  2  3  4  5
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
下边是魔方阵B:
12 16 25 4  8
6  15 19 23 2
5  9  13 17 21
24 3  7  11 20
18 22 1  10  14
先假设n阶奇次魔方阵B是存在的,从A中可以看出,B的任一元素在A中都有唯一确定的行号和列号组合(y,x)。
分离出B中所有元素在A中的行号y来构成n×n方阵I,让I(i,j)等于从B(i,j)分离出来的y;(如I(1,1) =3,即12在A中的行号A(3,2);I(1,2)=4,即16在A中的行号A(4,1)。)以下是I方阵:
3  4  5  1  2
2  3  4  5  1
1  2  3  4  5
5  1  2  3  4
4  5  1  2  3
同样分离出B中所有元素在A中的列号y来构成n×n方阵J,让J(i,j)等于从B(i,j)分离出来的x。以下是J方阵
2  1  5  4  3
1  5  4  3  2
5  4  3  2  1
4  3  2  1  5
3  2  1  5  4
观察方阵I特征为:

        1.组成方阵的数为1~n的整数;

        2.任一行、列均遍历1~n的所有整数;

        3.主对角线上的数均为(n+1)/2,辅对角线遍历1~n的所有整数。

方阵J特征前两点同I,区别是第三点,辅对角线上的数均为(n+1)/2,主对角线遍历1~n的所有整数。 另外还有轻易忽略的一点,I、J方阵对应位置上的数字组合[I(i,j),J(i,j)]是唯一的。
       综合以上的结论可以知道:B(i,j)=(I(i,j)-1)×n+J(i,j)。所以只要构造出这样两个只含1~n的数的方阵I和J,就可以确定一个n×n的魔方阵。
现在,问题就转化为怎样构造分别满足I和J的特征的两个n×n方阵。其实完成这样的算法是很简单的                                   (╮(╯▽╰)╭。。但是想到这里的人是基本上没有的。。。),可以按以下方法实现:

1) 方阵I的第一行由(n+1)/2打头,后面依次为前一个数关于n的循环后继;

2)方阵I的第i+1行由第i行循环右移得到。

小诸葛可以给出的最简程序:

#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,i,j;
int a[20][20],x[20][20],y[20][20];/* a数组为最后结果数组文中的B方阵,X,Y分别是文中提到的数组I,J*/
printf("please input the number:");
scanf("%d",&n); /*输入需要的数组维数*/
 x[0][0]=(n+1)/2;
 for(j=1;j<n;j++)
  {
   if(x[0][j-1]==n) x[0][j]=x[0][j-1]+1-n;
   else            x[0][j]=x[0][j-1]+1;
 }/*给x中的第一行元素赋值*/

for(i=1;i<n;i++)
 for(j=0;j<n;j++)
  {
    if(j-1<0) x[i][j]=x[i-1][j-1+n];
    else       x[i][j]=x[i-1][j-1];
} /*通过变换给X的所有元素赋值*/
system("cls");
printf("X:\n");
for(i=0;i<n;i++)
 for(j=0;j<n;j++)
 {
 printf("%3d",x[i][j]);
 if(j==n-1)printf("\n");
 }/*输出X数组*/
for(i=0;i<n;i++)
 for(j=0;j<n;j++)
 y[i][j]=x[i][n-1-j];/*通过文中提到的公式给Y数组赋值*/
printf("Y:\n");
for(i=0;i<n;i++)
 for(j=0;j<n;j++)
   {printf("%3d",y[i][j]);
   if(j==n-1)printf("\n");
   }/*输出Y数组*/
for(i=0;i<n;i++)
 for(j=0;j<n;j++)
   a[i][j]=(x[i][j]-1)*n+y[i][j];
printf("A:\n");
for(i=0;i<n;i++)
 for(j=0;j<n;j++)
 {printf("%5d",a[i][j]);
 if(j==n-1)printf("\n");}
/*输出A数组结果*/
     return 0;
}

上一个:c语言 三角形
下一个:怎样学好C语言

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,