N阶幻方阵

来源:互联网 发布:手机淘宝掌柜热卖截图 编辑:程序博客网 时间:2024/04/28 21:26

 

幻方,亦称纵横图。台湾称为魔术方阵。将自然数1,2,3,……n*n排列成一个n*n方阵,使得每行、每列以及两对角线上的各个数之和都相等,等于n/2*(n*n+1),这样的方阵称为幻方。

例如:把1,2,3,4,5,6,7,8,9填入3*3的格子,使得:每行、每列、两条对角线的和是15。

816357492

n是它的阶数,比如上面的幻方是3阶。n/2*(n*n+1)为幻方的变幻常数。数学上已经证明,对于n>2,n阶幻方都存在。

目前填写幻方的方法,是把幻方分成了三类,每类又有各种各样的填写方法。这里对于这三类幻方,仅举出一种方便手工填写的方法。

1、奇数阶幻方

n为奇数 (n=3,5,7,9,11……) (n=2*k+1,k=1,2,3,4,5……)

奇数阶幻方最经典的填法是罗伯特法(也有人称之为楼梯方)。填写方法是这样:

把1(或最小的数)放在第一行正中; 按以下规律排列剩下的n*n-1个数: 

(1)、每一个数放在前一个数的右上一格;

(2)、如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列; 

(3)、如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;

(4)、如果这个数所要放的格已经超出了顶行且超出了最右列,那么就把它放在前一个数的下一行同一列的格内; 

(5)、如果这个数所要放的格已经有数填入,处理方法同(4)。

这种写法总是先向“右上”的方向,象是在爬楼梯。

快速算法:

#include<stdio.h>
int mod(int i,int p)
{
 if(i>=0)return i%p==0?p:i%p;
 else  return p+i;
}
void main()
{
    int i,j,p,n;
    scanf("%d",&p);n=(p-1)/2;
    for(i=1;i<=p;i++)
    {
        for(j=1;j<=p;j++)printf("%4d",p*(mod(i+j-n-1,p)-1)+mod(j+mod(i+j-n-1,p)-n-1,p));
        printf("\n");
    }
    getch();
}

普通算法:

#include<stdio.h>
#include"malloc.h"
void main(void)
{
  int i,j,n,N,a,b,temp1,temp2;
  int *p;
  puts("Please  input the number!");
  scanf("%d",&N);
  
  p = (int *)malloc(sizeof(int)*N*N);
  for(i = 0;i<N*N;i++)
 p[i] = i+1;
  for(n=1;n<=N;n++)
  {
    i=j=n;
    a=(i-1)*N+j-1;
    p[a]=N*N+1-p[a];
    temp1=N-j+1;
 a=(i-1)*N+temp1-1;
    p[a]=N*N+1-p[a];
    for(b=1;b<N/4;b++)
    {
        j=j+4;
        temp2=j%N;
  if(temp2==0)
   temp2=8;
        a=(i-1)*N+temp2-1;
        p[a]=N*N+1-p[a];
  temp2=N-temp2+1;
  a=(i-1)*N+temp2-1;
        p[a]=N*N+1-p[a];
     }
  }
 for(i = 0;i<N*N;i++)
 {
    printf("%4d",p[i]);
    if((i+1)%N == 0)
    printf("\n");
  }
}
  


2、双偶阶幻方

n为偶数,且能被4整除 (n=4,8,12,16,20……) (n=4k,k=1,2,3,4,5……)

先说明一个定义:

互补:如果两个数字的和,等于幻方最大数和最小数的和,即 n*n+1,称为互补。

先看看4阶幻方的填法:将数字从左到右、从上到下按顺序填写:

12345678910111213141516

这个方阵的对角线,已经用蓝色标出。将对角线上的数字,换成与它互补的数字。

这里,n*n+1 = 4*4+1 = 17;

把1换成17-1 = 16;把6换成17-6 = 11;把11换成17-11 = 6……换完后就是一个四阶幻方。

16231351110897612414151

对于n=4k阶幻方,我们先把数字按顺序填写。写好后,按4*4把它划分成k*k个方阵。因为n是4的倍数,一定能用4*4的小方阵分割。然后把每个小方阵的对角线,象制作4阶幻方的方法一样,对角线上的数字换成互补的数字,就构成幻方。 下面是8阶幻方的作法:

(1) 先把数字按顺序填。然后,按4*4把它分割成2*2个小方阵

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364

(2) 每个小方阵对角线上的数字,换成和它互补的数。

64236160675795554121351501617474620214342244026273736303133323435292838392541232244451918484915145253111056858595462631

算法实现:

#include<stdio.h>
#include"malloc.h"
void main(void)
{
  int i,j,n,N,a;
  int *p;
  puts("Please  input the number!");
  scanf("%d",&N);
  p = (int *)malloc(sizeof(int)*N*N);
  for(i = 0;i<N*N;i++)
  {
    p[i] = 0;
  }
  i = 1;
  j = N/2+1;
  for(n=1;n<=N*N;n++)
  { 
 if(i ==0 && j==N+1)
     {
            i = i+2;
            j = j-1;
     }
  if(i == 0)
          i = i+N;
        if(j == N+1)
          j = j-N;
  a = (i-1)*N+j-1;
     if(p[a] != 0)
     {
            i = i+2;
            j = j-1;
     }  
  a = (i-1)*N+j-1;
  p[a] = n;
  i = i-1;
  j = j+1;
  }
 for(i = 0;i<N*N;i++)
 {
    printf("%4d",p[i]);
    if((i+1)%N == 0)
 printf("\n");
  }
}
  


3、单偶阶幻方

n为偶数,且不能被4整除 (n=6,10,14,18,22……) (n=4k+2,k=1,2,3,4,5……)

这是三种里面最复杂的幻方。

以n=10为例。这时,k=2

(1) 把方阵分为A,B,C,D四个象限,这样每一个象限肯定是奇数阶。用楼梯法,依次在A象限,D象限,B象限,C象限按奇数阶幻方的填法填数。

                      A    B                                            C    D                      

172418156774515865235714167355576466461320225456637072101219213606269715311182529616875525992997683904249263340988082899148303239417981889597293138454785879496783537444628869310077843643502734

(2) 在A象限的中间行、中间格开始,按自左向右的方向,标出k格。A象限的其它行则标出最左边的k格。

>>>

172418156774515865235714167355576466461320225456637072101219213606269715311182529616875525992997683904249263340988082899148303239417981889597293138454785879496783537444628869310077843643502734

(3) 将这些格,和C象限相对位置上的数,互换位置。

929918156774515865988071416735557646646889522545663707285871921360626971538693252961687552591724768390424926334023582899148303239417981132097293138454710129496783537444628111810077843643502734

(4) 在B象限任一行的中间格,自右向左,标出k-1列。(注:6阶幻方由于k-1=0所以不用再作B、D象限的数据交换)

             <<<   

929918156774515865988071416735557646646889522545663707285871921360626971538693252961687552591724768390424926334023582899148303239417981132097293138454710129496783537444628111810077843643502734

(5) 将B象限标出的这些数,和D象限相对位置上的数进行交换,即可完成。

 

929918156774265865988071416735532646646889522545638707285871921360624471538693252961685052591724768390424951334023582899148305739417981132097293163454710129496783537694628111810077843643752734

幻方阵c语言实现:

 


原创粉丝点击