魔方阵 奇数偶数都成立
《C程序设计(第四版)》 谭浩强的,第六章 第7题 有一个输出 魔方阵的题,相信困惑了不少人,下面本文给予大家完整的解答。
所谓魔方阵即1-N*N个数排成一个n阶矩阵,矩阵特点:每一行,每一列,对角线之和都等于相同的值。
下面根据资料总结得到:
1):奇数的魔方阵:
其数字排列规则如下:
1)将1填入第一行中间;
2)将每个数填在前一个数的右上方。
3)若该位置超出最上行,则改填在最下行的对应位置;
4)若该位置超出最右列,则该填在最左列的对应行位置;
5)若某元素填在第一行最右列,下一个数填在该数同列的下一行;
6)若某数已找到了填写位置,但其已填了其他数据,则这个数应填在应该填的位置的同列的下一行位置。
自己的代码如下:
#include<stdio.h> //此为求奇魔方阵的方法
#include<string.h>
int main()
{
int a[100][100],i,j,n,k,x,y;
printf("Enter n:\n");
while(scanf("%d",&n)!=EOF&&(n%2==1))
{
memset(a,0,sizeof(a));//将原始数组全部清0;必须清零
i=0;
j=n/2;
a[i][j]=1; //第一条
for(k=2;k<=n*n;k++)
{
x=i; //x,y记录原来一个数的坐标
y=j;
i--;
j++;
if(i<0)i=n-1; //第二条
if(j>n-1)j=0; //第三条
if(a[0][n-1]!=0)//第四条 此条可以省略
{
a[1][n-1]=a[0][n-1]+1;
}
if(a[i][j]!=0)// 第五条
{
i=x+1;
j=y;
}
a[i][j]=k;
}
for(i=0;i<n;i++) //输出此数组
{
for(j=0;j<n;j++)
printf("%4d",a[i][j]);
putchar('\n');
}
printf("Enter n:\n");
}
return 0;
}
2):双偶数魔方阵:
所谓双偶数即2*(2m)的数据,即4的整数倍,期排列特点如下:
1:把魔方阵分为上下左右4个n/2*n/2的小的方阵,左上角和右下角的n/2*n/2的小矩阵
2:偶行偶列,奇行奇列赋值为0,其余赋值为1;右上角和左上角的n/2*n/2的小矩阵,偶行奇列,奇行偶列赋值为0,其余赋值为1。
3:从魔方阵由左到右,由上到下开始赋值,赋值为从n*n到1,若遇到原来填入方阵中的0,则跳过此格;
4:从魔方阵由左到右,由上到下开始赋值,赋值为从1到n*n,若遇到原来填入方阵中的1,则跳过此格;
5:填完数据后则完成 双偶数魔方阵;
我的代码如下:
#include<stdio.h>//双偶数的魔方阵 即4*m阶 (m=1,2,3...)
#include<string.h>
int main()
{
int n,a[100][100],i,j,k;
while(scanf("%d",&n)!=EOF&&(n%4==0)&&n>0)
{
memset(a,0,sizeof(a));
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(i<n/2&&j<n/2||i>=n/2&&j>=n/2) //分别填入 0和1
if(i%2==0&&j%2==1||i%2==1&&j%2==0)
a[i][j]=1;
if(i>=n/2&&j<n/2||i<n/2&&j>=n/2)
if(i%2==0&&j%2==0||i%2==1&&j%2==1)
a[i][j]=1;
}
k=n*n;
for(i=0;i<n;i++) //填入n*n到1
for(j=0;j<n;j++)
{
if(a[i][j]==1)a[i][j]=k;
k--;
}
k=1;
for(i=0;i<n;i++)//填入1到n*n 并输出魔方阵
{
for(j=0;j<n;j++)
{
if(a[i][j]==0)a[i][j]=k;
k++;
printf("%4d",a[i][j]);
}
putchar('\n');
}
}
}
3):单偶数魔方阵
所谓单偶数,即n=2*(2m+1)的数据,其数字排列特点如下:
1:将矩阵分为4个区,A、B、C、D区,其相对位置如下:
A | C |
D | B |
2:先把数字1到(n/2)*(n/2)按照奇数魔方阵的方法填入A中,然后把其每一个数据分别加上(n/2)*(n/2)填入到B中,再把B中的数据加上(n/2)*(n/2)填入到C中,再把C中的数据加上(n/2)*(n/2)填入到D中;
3:交换数字
需要交换的数字的规则:
1: 右边两个小方阵中大于(m+2)的列中所有的数字
2: 左边两个小方阵中(m+1,m+1)这一个方格的数字
3: 左边两个小方阵中除(m+1,1)格位之外,小于m+1的列中的所有数字
其中n=2*(2m+1);即m=(n-2)/4;
比如说n=6,即m=1这个例子;
先把这些数字做标记:如图
只需要标记A区和C区数字即可,然后A区和D区数字对应交换,
C区和B区数字对应进行交换,此例C区没有交换数字:
8 | 1 | 6 | 26 | 19 | 24 |
3 | 5 | 7 | 21 | 23 | 25 |
4 | 9 | 2 | 22 | 27 | 20 |
35 | 28 | 33 | 17 | 10 | 15 |
30 | 32 | 34 | 12 | 14 | 16 |
31 | 36 | 29 | 13 | 18 | 11 |
然后交换即得到单偶数魔方阵:如下图:
35 | 1 | 6 | 26 | 19 | 24 |
3 | 32 | 7 | 21 | 23 | 25 |
31 | 9 | 2 | 22 | 27 | 20 |
8 | 28 | 33 | 17 | 10 | 15 |
30 | 5 | 34 | 12 | 14 | 16 |
4 | 36 | 29 | 13 | 18 | 11 |
代码如下:
#include<stdio.h> // A C A、B、C、D四块的相对位置
#include<string.h> // D B
#define M 100
void output(int a[][M],int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%4d",a[i][j]);
printf("\n");
}
}
int main()
{
int a[100][100],i,j,k,x,y,n,m,t;
printf("请输入单偶数n:\n");
while(scanf("%d",&n)!=EOF)
{
memset(a,0,sizeof(a));
//输入A矩阵
a[0][n/2/2]=1;
i=0;
j=n/2/2;
for(k=2;k<=(n/2*n/2);k++)
{
x=i;
y=j;
i--;
j++;
if(i<0)i=n/2-1;
if(j>n/2-1)j=0;
if(a[i][j]!=0)
{
i=x+1;
j=y;
}
a[i][j]=k;
}
//输入B矩阵
for(i=n/2;i<n;i++)
for(j=n/2;j<n;j++)
{
a[i][j]=a[i-n/2][j-n/2]+(n/2)*(n/2);
}
//C...
for(i=0;i<n/2;i++)
for(j=n/2;j<n;j++)
{
a[i][j]=a[i+n/2][j]+(n/2)*(n/2);
}
//D...
for(i=n/2;i<n;i++)
for(j=0;j<n/2;j++)
{
a[i][j]=a[i-n/2][j+n/2]+(n/2)*(n/2);
}
//交换数字
//A和D换 因为n=2*(2m+1),所以m=(n-2)/4
//步骤1: 交换第(m+1,m+1)格
m=(n-2)/4;
t=a[m][m];
a[m][m]=a[m+n/2][m];
a[m+n/2][m]=t;
//2:交换除了(m+1,1)格以外的小于m+1的列
for(i=0;i<n/2;i++)
for(j=0;j<n/2;j++)
{
if(j<m)
{
if(i==m&&j==0)continue;
t=a[i][j];
a[i][j]=a[i+n/2][j];
a[i+n/2][j]=t;
}
}
//C和B的交换
for(i=0;i<n/2;i++)
for(j=n/2;j<n;j++)
{
if(j>n/2+m+1)
{
t=a[i][j];
a[i][j]=a[i+n/2][j];
a[i+n/2][j]=t;
}
}
output(a,n); //输出魔方阵
printf("请输入单偶数n:\n");
}
return 0;
}
好了,这就是1--n阶的魔方阵,当然魔方阵的排列规则有很多,还可以构造魔方阵,只要记住其中一种方法就可以了,若要看整合的代码,并带有检测是否为魔方阵的环节,请看下篇魔方阵(2),这就是魔方阵的全面解答,与大家分享,此文若有有不足之处或错误请指正;