魔方陣 奇數偶數都成立


 

《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區沒有交換數字:

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 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),這就是魔方陣的全面解答,與大家分享,此文若有有不足之處或錯誤請指正;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM