魔方矩阵

snjsj 我的程序算法:  
  这个魔方阵的算法可以对除2以外的任意阶数的方阵进行输出,结果保存在运行程序的目录下面的Magic.txt文件中,用ie或者写字板打开以保持格式的一致(主要是回车符在记事本中为黑方框,认不出来)。当然具体的程序中,有内存空间以及变量范围的约束,我试过了,100以内的是可以的。  
          偶数阶的算法都是建立在奇数阶的基础之上,设方阵的阶数为n,则魔方阵常数(即每列每行以及对角线元素之和)为n*(n*n+1)/2。  
   
  请对照程序代码看,否则可能看不懂,可以一边看一边用笔对小阶的进行演算。  
   
          先说奇数阶的算法,这是最容易的算法:  
  n=2*m+1,m为自然数  
  1)将数字1填在(0,(n+1)/2)   ;要注意c中是从下标0开始  
  2)从左上往右下依次填。  
  3)由2),列的下标出界(超过n-1)时,行加1,以n为摸的余数为应填的列数;  
  4)由2),行的下标出界(超过n-1)时,列加1,以n为摸的余数为应填的行数;  
  5)由2),行列都未出界,但已添上其他数,应在当前位置左横移一个位置进行填数。  
   
  然后是偶数阶:  
  分两种情况,一种是n%4==2,一种是n%4==0  
  前一种:n=2*(2*m+1),m为自然数  
  1)将n阶方阵分为四个小魔方阵ABCD如下排列:  
   
  B   C  
  D   A  
   
  因为n*n=4*(2*m+1)*(2*m+1),  
  记u=n/2=2*m+1,分为1~u*u,u*u+1~2*u*u,2*u*u+1~3*u*u,3*u*u+1~4*u*u  
  即在调用子函数的时候分别如下面传递参数:  
  A(0),B(u*u),C(2*u*u),D(3*u*u)  
  分别在ABCD中按照前面的填法把奇数阶填好(注意加上所传参数作为基数,每一个元素都要加上这个值),最后做如下交换:  
  (1)B中第0~(m-1)-1行中元素与C中相对应元素交换  
  (2)D中第(n-1)-m+1~(n-1)共m行的每行中的元素与A中相对应元素交换  
  (3)交换D:(u+m,m)与A中对应元素(矩阵中心值)  
  (4)交换D:(n-1,m)与A中对应元素(实际为矩阵最大值n*n)  
   
  所谓对应位置,指相对于小魔方阵的左顶角的相对的行列位置  
  上面的这些你可以用数学进行证明,利用魔方阵常数(注意n阶的和u阶的关系)  
   
  后一种:n=4*m,m为自然数  
  因为行列都是4的倍数,因而可以将整个矩阵分为每4*4的小矩阵。  
  先判断一个数是否在划为4*4小矩阵的对角线上,  
  如果在,则填该位置的数为n*n-i+1(i为该元素的相对位置,从1开始,比如n阶的第s行第t个元素则其i=s*n+t)  
  如果不在,则填上i。


 
  #include<stdio.h>  
  #include<stdlib.h>  
  int   N;  
  int   *M=NULL;  
   
  void   main()  
  {  
  int   i;  
  int   check(int,int);  
  void   out();  
  void   set_3_5(int,int,int,int);  
  void   set_4();  
  void   set_6();  
  void   swap(int,int);  
   
  printf("Press   any   key   to   start:");  
  getch();  
  printf("/r");  
    Begin:  
   
  printf("Input   the   rank   of   the   Magic   Matrix:");  
  scanf("%d",&N);  
  if(N<=2){printf("/007/n/nInput   Error!Try   again!/n");goto   Begin;}  
  M=(int   *)calloc(N*N+1,sizeof(int));  
  if(M==NULL)  
      {printf("/007/nError:Out   of   memory!/n");  
        goto   Next;  
      }  
   
  for(i=0;i<N*N;i++){*(M+i)=0;}  
  switch(N%4)  
      {case   0:set_4();break;  
        case   2:set_6();break;  
        default:i=N;set_3_5(0,0,i,0);  
      }  
  out();  
  free(M);  
   
    Next:  
   
  printf("/nWould   you   like   to   go   on?/nPress   Esc   to   exit,any   other   key   to   continue:");  
  i=getch();  
  if(i!=27){putchar('/n');goto   Begin;}  
      else   printf("/007/nThanks   for   use./n");  
  }  
   
  int   check(int   i,int   j)  
  {switch(i%4)  
      {case   0:  
        case   3:if(j%4==0||j%4==3)return(1);  
          else   return(0);  
        default:if(j%4==1||j%4==2)return(1);  
              else   return(0);  
      }  
  }  
   
  void   set_3_5(int   i0,int   j0,int   mod,int   base)  
  {int   i_try,j_try,k,i=0,j=mod/2;  
    *(M+(i+i0)*N+j+j0)=1+base;  
    for(k=2;!(k>mod*mod);k++)  
        {i_try=i-1,j_try=j-1;  
          if(i_try<0)i_try=mod-1;  
          if(j_try<0)j_try=mod-1;  
          if(*(M+(i_try+i0)*N+j_try+j0)||i==0&&j==0){i_try=i+1,j_try=j;}  
          i=i_try;j=j_try;  
          *(M+(i+i0)*N+j+j0)=k+base;  
        }  
  }  
   
  void   set_4()  
  {int   i,j,c=N*N;  
    for(i=0;i<N;i++)  
        {for(j=0;j<N;j++)  
            {if(check(i,j)){*(M+i*N+j)=c-i*N-j;}  
  else   {*(M+i*N+j)=i*N+j+1;}  
            }  
        }  
  }  
   
  void   set_6()  
  {int   i,j,m,u;  
    u=N/2;  
    m=(u-1)/2;  
    set_3_5(0,0,u,u*u);  
    set_3_5(0,u,u,2*u*u);  
    set_3_5(u,0,u,3*u*u);  
    set_3_5(u,u,u,0);  
    for(i=0;i<m-1;i++)  
        for(j=0;j<u;j++)  
            swap(i,j);  
    for(i=0;i<m;i++)  
        for(j=0;j<u;j++)  
            swap(N-1-i,j);  
    swap(u+m,m);  
    swap(N-1,m);  
  }  
   
  void   swap(int   i,int   j)  
  {int   p=*(M+i*N+j);  
    *(M+i*N+j)=*(M+i*N+j+N/2);  
    *(M+i*N+j+N/2)=p;  
  }  
   
  void   out()  
  {int   i,j;  
    FILE   *fp;  
    float   c=(float)N*((float)N*(float)N+1)/2;  
   
    fp=fopen("Magic.txt","wb+");  
    if(fp==NULL)  
        {printf("Create   file   ERROR!/n");  
          exit(0);  
        }  
    else  
        printf("/007/nYou   can   find   the   result   in   the   Magic.txt   where   you   run   the   program./n");    
   
    for(i=0;i<N;i++)  
        {for(j=0;j<N;j++)  
              fprintf(fp,"%8d",*(M+i*N+j));  
          fprintf(fp,"/n");  
        }    
   
    fprintf(fp,"Magic   Matrix   rank=%d,Magic   constant=%.0f./n",N,c);  
    fclose(fp);  
  }  
 


  #include<stdio.h>  
  #include<math.h>  
  #define   n   9  
  long   aver;  
  long   chazhi(long   a[n][n])  
  {long   i,j,m=0,x=0;  
  for(i=0;i<n;i++)  
      {for(j=0;j<n;j++)x+=a[i][j];  
      m+=(x-aver)*(x-aver)*(x-aver)*(x-aver);x=0;}  
  for(j=0;j<n;j++)  
      {for(i=0;i<n;i++)x+=a[i][j];  
      m+=(x-aver)*(x-aver)*(x-aver)*(x-aver);x=0;}  
  for(i=0;i<n;i++)x+=a[i][i];  
  m+=(x-aver)*(x-aver)*(x-aver)*(x-aver);x=0;  
  for(i=0;i<n;i++)x+=a[i][n-i-1];  
  m+=(x-aver)*(x-aver)*(x-aver)*(x-aver);x=0;  
  return(m);  
  }  
  main()  
  {long   a[n][n],i,j,k,t,s,m,jj,cha,b[n];  
  m=1;  
  for   (i=0;i<n;i++)  
      for(j=0;j<n;j++){a[i][j]=m++;printf("%d/n",a[i][j]);}  
  m=0;  
  for(i=1;i<=n*n;i++)m+=i;  
  aver=m/n;printf("%d",aver);  
  cha=chazhi(a);printf("%8d/n",cha);  
  /*while(cha!=0)*/for(jj=0;jj<23;jj++)  
  {printf("%8d",cha);  
  for(i=0;i<n;i++)  
      {for(j=0;j<n;j++)b[j]=a[i][j];  
      t=chazhi(a);  
      for(j=1;j<n;j++)  
          {s=a[i][0];  
          for(k=0;k<n-1;k++)a[i][k]=a[i][k+1];  
          a[i][n-1]=s;  
          s=chazhi(a);  
          if(t>s)  
              {t=s;for(k=0;k<n;k++)b[k]=a[i][k];  
              }  
          }  
      for(j=0;j<n;j++)a[i][j]=b[j];  
      cha=t;  
      }  
  if(cha!=0)  
      {for(j=0;j<n;j++)  
          {for(i=0;i<n;i++)b[i]=a[i][j];  
          t=chazhi(a);  
          for(i=1;i<n;i++)  
              {s=a[0][j];  
              for(k=0;k<n-1;k++)a[k][j]=a[k+1][j];  
              a[n-1][j]=s;  
              s=chazhi(a);  
              if(t>s)  
  {t=s;for(k=0;k<n;k++)b[k]=a[k][j];  
  }  
              }  
          for(i=0;i<n;i++)a[i][j]=b[i];  
          cha=t;  
          }  
      }  
  if(cha!=0)  
      {for(i=0;i<n;i++)b[i]=a[i][i];  
      t=chazhi(a);  
      for(i=1;i<n;i++)  
          {s=a[0][0];  
          for(k=0;k<n-1;k++)a[k][k]=a[k+1][k+1];  
          a[n-1][n-1]=s;  
          s=chazhi(a);  
          if(t>s)  
              {t=s;for(k=0;k<n;k++)b[k]=a[k][k];  
              }  
          }  
      for(i=0;i<n;i++)a[i][i]=b[i];  
      cha=t;  
      }  
  if(cha!=0)  
      {for(i=0;i<n;i++)b[i]=a[i][n-i-1];  
      t=chazhi(a);  
      for(i=1;i<n;i++)  
          {s=a[0][n-1];  
          for(k=0;k<n-1;k++)a[k][n-k-1]=a[k+1][n-k-2];  
          a[n-1][0]=s;  
          s=chazhi(a);  
          if(t>s)  
              {t=s;for(k=0;k<n;k++)b[k]=a[k][n-k-1];  
              }  
          }  
      for(i=0;i<n;i++)a[i][n-i-1]=b[i];  
      cha=t;  
      }  
  }  
  printf("/n");  
  for(i=0;i<n;i++)  
      {for(j=0;j<n;j++)printf("%8d",a[i][j]);  
      printf("/n");  
      }  
  scanf("%c");  
  }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值