N阶幻方阵

 

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

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

816
357
492

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阶幻方的填法:将数字从左到右、从上到下按顺序填写:

1234
5678
9101112
13141516

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

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

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

162313
511108
97612
414151

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

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

12345678
910111213141516
1718192021222324
2526272829303132
3334353637383940
4142434445464748
4950515253545556
5758596061626364

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

642361606757
955541213515016
1747462021434224
4026273736303133
3234352928383925
4123224445191848
4915145253111056
858595462631

算法实现:

#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  
          
          

172418156774515865
235714167355576466
461320225456637072
1012192136062697153
111825296168755259
92997683904249263340
98808289914830323941
79818895972931384547
85879496783537444628
869310077843643502734

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

>>>

172418156774515865
235714167355576466
461320225456637072
1012192136062697153
111825296168755259
92997683904249263340
98808289914830323941
79818895972931384547
85879496783537444628
869310077843643502734

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

929918156774515865
9880714167355576466
468895225456637072
8587192136062697153
869325296168755259
17247683904249263340
2358289914830323941
79811320972931384547
10129496783537444628
111810077843643502734

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

             <<<   

929918156774515865
9880714167355576466
468895225456637072
8587192136062697153
869325296168755259
17247683904249263340
2358289914830323941
79811320972931384547
10129496783537444628
111810077843643502734

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

 

929918156774265865
9880714167355326466
468895225456387072
8587192136062447153
869325296168505259
17247683904249513340
2358289914830573941
79811320972931634547
10129496783537694628
111810077843643752734

幻方阵c语言实现:

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值