LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1945|回复: 31

求能计算所有方阵的程序

[复制链接]
发表于 2003-7-6 19:28:34 | 显示全部楼层 |阅读模式
N 阶方阵是 把 1 - N^2 填在 N*N 的矩阵里 ,
使得 每行、每列、对角线的和都相等;
N 能做到多大就多大拉。

下面是我的一个程序(N=5 时就难于忍受了):

  1. /***********************

  2. *** Fifth version  *****

  3. ***********************/



  4. #include<time.h>

  5. #include<stdio.h>



  6. #define Max 100


  7. int END;

  8. int M;

  9. int sum;

  10. int maxnum,minnum;

  11. int data[Max*Max];

  12. int flags[Max*Max];

  13. FILE *outfile;

  14. time_t start,end;

  15. int bottom,top,left;

  16. int head,tail,cursor;





  17. void init();

  18. void bye();

  19. void range(int);

  20. void magic(int);

  21. void output(void);

  22. void print_status(void);







  23. main()

  24. {

  25. init();

  26. magic(0);

  27. bye();

  28. return 0;

  29. }





  30. void init()

  31. {



  32. int i;



  33. outfile=fopen("result.txt","w");



  34. for(i=0;i<Max*Max;i++)flags[i]=0;

  35. printf("    Input M:");

  36. scanf("%d",&M);



  37. sum=(M*M+1)*M/2;

  38. END=M*M-1;


  39. start=time(&start);

  40. fprintf(outfile,"start at %s\n//////////////////////////////////\n",ctime(&start));



  41. }



  42. void bye()

  43. {

  44. end=time(&end);

  45. fprintf(outfile,"\n//////////////////////////////////\nend at %s\n",ctime(&end));

  46. fclose(outfile);


  47. }



  48. void magic(int n)

  49. {

  50. int i;

  51. int max;



  52. range(n);

  53. i=minnum;

  54. max=maxnum;



  55.         for(;i<=max;i++)

  56.                 {if(flags[i]==0){

  57.                         flags[i]=1;

  58.                         data[n]=i+1;

  59.                          if(n==(END)){output(); }

  60.                          else magic(n+1);

  61.                          flags[i]=0;

  62.                         }

  63.                 }

  64.         return;

  65. }





  66. void output()

  67. {

  68. int i,j;



  69. for(i=0;i<M;i++)

  70.         {for(j=0;j<M;j++)

  71.                 {

  72.                 fprintf(outfile,"%5d",data[i*M+j]);

  73.                 }

  74.         fputc('\n',outfile);

  75.         }

  76. fputs("*****************************************\n",outfile);

  77. fflush(outfile);

  78. }







  79. /*******************  This function to large!!!        ************/
  80. /* calculate the range for the next data */

  81. void range(int n)     //not so easy to understand.

  82. {

  83. static int i,j,k;

  84. static int used=0;

  85. used=0;

  86. i=(n/M)*M;

  87. cursor=n%M;

  88. j=i+cursor;

  89. left=sum;

  90. for(;i<j;i++)

  91.         used+=data[i];



  92. k=M-cursor-1;

  93. top=bottom=sum-used-1;

  94. for(i=END;k>0;i--)

  95.         if(flags[i]==0)

  96.                 {bottom-=i+1;k--;}

  97. tail=END;

  98. k=M-cursor-1;

  99. for(i=0;k>0;i++)

  100.         if(flags[i]==0)

  101.                 {top-=i+1;k--;}

  102. head=0;

  103. for(;flags[head]!=0;head++);

  104.        

  105.         minnum=bottom>head?bottom:head;

  106.        

  107. for(;flags[tail]!=0;tail--);

  108.         maxnum=top<tail?top:tail;





  109. cursor=n/M;

  110. j=(n%M);

  111. for(used=0,i=0;i<cursor;i++)

  112.         used+=data[i*M+j];



  113. top=bottom=sum-used-1;





  114. for(i=END,k=M-cursor-1;k>0;i--)

  115.         if(flags[i]==0)

  116.                 {bottom-=i+1;k--;}



  117. for(i=0,k=M-cursor-1;k>0;i++)

  118.         if(flags[i]==0)

  119.                 {top-=i+1;k--;}



  120. minnum=minnum>bottom?minnum:bottom;

  121. maxnum=maxnum<top?maxnum:top;



  122. if(cursor==j)

  123. {



  124. for(used=0,i=0;i<cursor;i++)

  125.         used+=data[i*M+i];



  126. top=bottom=sum-used-1;





  127. for(i=END,k=M-cursor-1;k>0;i--)

  128.         if(flags[i]==0)

  129.                 {bottom-=i+1;k--;}



  130. for(i=0,k=M-cursor-1;k>0;i++)

  131.         if(flags[i]==0)

  132.                 {top-=i+1;k--;}

  133. minnum=minnum>bottom?minnum:bottom;

  134. maxnum=maxnum<top?maxnum:top;

  135. }



  136. if((cursor+j+1)==M)

  137. {



  138. for(used=0,i=0,j=M-1;i<cursor;i++,j--)

  139.         used+=data[i*M+j];



  140. top=bottom=sum-used-1;





  141. for(i=END,k=M-cursor-1;k>0;i--)

  142.         if(flags[i]==0)

  143.                 {bottom-=i+1;k--;}



  144. for(i=0,k=M-cursor-1;k>0;i++)

  145.         if(flags[i]==0)

  146.                 {top-=i+1;k--;}

  147. minnum=minnum>bottom?minnum:bottom;

  148. maxnum=maxnum<top?maxnum:top;

  149. }

  150. }

复制代码
 楼主| 发表于 2003-7-6 19:48:07 | 显示全部楼层
这个很难的。
如果有人在 10 天内写出程序,用 1 hour 计算出 N=10的所有方阵的话,我跳楼算了!!
发表于 2003-7-6 20:43:21 | 显示全部楼层
你跳楼吧
发表于 2003-7-6 20:52:16 | 显示全部楼层
问题表述不清楚,没有说清是否是 数字1到N^2 添入的数字是否允许重复.
发表于 2003-7-6 21:04:56 | 显示全部楼层
这种方阵称为幻方。是一个历史悠久的数学问题。看看这个就清楚了。
http://yamaths.myrice.com/zhghf/
发表于 2003-7-6 21:44:45 | 显示全部楼层
随手写了一个,中间的循环部分怎么看都觉得难看的很,呵呵
这个程序只能处理奇数的方阵,偶数的我还没搞懂。
(一个小时用不了吧,一秒钟就完了)

  1. #include <stdio.h>

  2. int *a;

  3. int main(int argc, char *argv[])
  4. {
  5.   int n, x, y, i;
  6.   
  7.   if(argc == 1){
  8.     fprintf(stderr, "usage: %s number\n", argv[0]);
  9.     exit(-1);
  10.   }

  11.   n = atoi(argv[1]);
  12.   a = (int *)calloc(n * n, sizeof(*a));
  13.   x = n / 2;
  14.   y = n - 1;
  15.   i = 1;
  16.   *(a + y * n + x) = i;
  17.   ++x; ++y; ++i;
  18.   while(i <= n * n){
  19.     if(i % n == 1){
  20.       y -= 2;
  21.       --x;
  22.     }
  23.     if(x >= n)
  24.       x = 0;
  25.     if(y >= n)
  26.       y = 0;
  27.     *(a + y * n + x) = i;
  28.     ++x; ++y; ++i;
  29.   }
  30.   for(y = n - 1; y >= 0; --y){
  31.     for(x = 0; x < n; ++x)
  32.       printf("%2d ", *(a + y * n + x));
  33.     printf("\n");
  34.   }
  35.   
  36.   free(a);
  37.   exit(0);
  38. }
复制代码
发表于 2003-7-6 22:05:18 | 显示全部楼层
libinary兄,楼主的意思是计算所有满足条件的方阵,不是只计算一个。
发表于 2003-7-6 22:16:40 | 显示全部楼层
哦,没搞懂楼主的意思。
 楼主| 发表于 2003-7-6 23:15:32 | 显示全部楼层
写奇数的我自己都还其它写法.

难的地方在于要写出所有的.
 楼主| 发表于 2003-7-6 23:17:07 | 显示全部楼层
最初由 maillistcs 发表
问题表述不清楚,没有说清是否是 数字1到N^2 添入的数字是否允许重复.


我认为大家都知道这样的问题.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表