louiset 2015-08-12 17:18 采纳率: 57.1%
浏览 1971
已采纳

请教一下魔方阵的问题。。

(每一行每一列以及对角线之和都相等的方阵)
要求输出1--n*n的魔方阵
(。。用的方法不好。。但是不知道哪里错了>_<)

#include
#include
int main()
{
int m[15][15],k,n,i,j;
for(n=2;n%2==0;)
{printf("enter your number:");
scanf("%d",&n);}
for(k=1,i=1,j=(n+1)/2;k<=n;k++)
{
m[i][j]=k;
if(i==1)
{
if(j==n)
{
l=m[n][1];
if(l==0) {m[n][1]=k+1;i=n;j=1;}
else {m[i+1][j]=k+1;i=i+1;}
}
else {
l=m[n][j+1];
if(l==0) {m[n][j+1]=k+1;i=n;j=j+1;}
else {m[i+1][j]=k+1;i=i+1;}
}
}
else
{
if(j==n)
{
l=m[i-1][1];
if(l==0) {m[i-1][1]=k+1;i=i-1;j=1;}
else {m[i+1][j]=k+1;i=i+1;}
}
}
l=m[i-1][j+1];
if(l==0) {m[i-1][j+1]=k+1;i=i-1;j=j+1;}
else {m[i+1][j]=k+1;i=i+1;}
}

for(i=1;i<=n;i++)
{ for(j=1;j<=n;j++)
printf("%d\t",m[i][j]);
printf("\n");
}

return 0;}

  • 写回答

2条回答 默认 最新

  • threenewbee 2015-08-12 21:52
    关注
     // app2.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    
    #include<stdio.h>
    #include<math.h>
    #define MAX 30
    int a[MAX][MAX];    // 幻方矩阵
    int n,s;    // n:阶数,s:幻方数
    int x,y;
    int i,j,k;
    int total,m;
    int ox,oy;
    void main()
    {
        void odd(int m, int index);
        void singleEven();
        void FourXFour();
        void doubleEven();
    
        do
        {
            printf("Please input n(3<=n[<=17]):\t");    // 屏幕可显示的最大阶数为17
            scanf("%d",&n);
            if(n<3) continue;   // 幻方最小阶数
            s=n*(pow(n,2)+1)/2; // 幻方数
            printf("s=%d\n",s);
            if(n%2==1){
                // 奇阶幻方
                ox=oy=0;
                odd(n,0);   // 从1开始填写n阶幻方
            }
            else if(n%4==0)
            {
                // 双偶阶幻方
                doubleEven();
    
            }
            else if(n%2==0)
            {
                // 单偶阶幻方
                singleEven();
    
            }
            // 输出制作好的n阶幻方
            for(i=0;i<n;i++)
            {
                s=0;
                for(j=0;j<n;j++)
                    s+=a[i][j],printf("%4d",a[i][j]);
                printf("\t=%d\n",s);
            }
            fflush(stdin);  // 清除多余或无效的输入
        }while(1);
    }
    /* 奇数阶幻方
    最经典的填法是罗伯特法(楼梯法),填写方法是这样:
    把1(或最小的数)放在第一行正中;按以下规律排列剩下的n×n-1个数: 
    (1)每一个数放在前一个数的右上一格;
    (2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
    (3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
    (4)如果这个数所要放的格已经超出了顶行且超出了最右列,那么就把它放在前一个数的下一行同一列的格内;
    (5)如果这个数所要放的格已经有数填入,处理方法同(4)。
    这种写法总是先向“右上”的方向,象是在爬楼梯。
    三阶幻方:
       8   1   6
       3   5   7
       4   9   2    */
    // 解奇阶幻方的通用模块
    // m 为阶数
    // index 为起始标识
    void odd(int m, int index)
    {
        x=m/2;
        y=0;
        for(i=index+1;i<=index+pow(m,2);i++)
        {
            a[oy+y][ox+x]=i;
            if(i%m==0) y++;
            else x++,y--;
            // else x++,y+=2; Hourse法
            x=(x%m+m)%m;
            y=(y%m+m)%m;
        }
    }
    /* 单偶阶幻方
    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象限按奇数阶幻方的填法填数。
    6阶幻方第一步:
       8   1   6 | 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
    (2) 在A象限的中间行、中间格开始,按自左向右的方向,标出k格。
    A象限的其它行则标出最左边的k格。
    将这些格,和C象限相对位置上的数,互换位置。
    6阶幻方第二步:
      35*  1   6 | 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
    (3) 在B象限任一行的中间格,自右向左,标出k-1列。
    (注:6阶幻方由于k-1=0,所以不用再作B、D象限的数据交换)
    将B象限标出的这些数,和D象限相对位置上的数进行交换,就形成幻方。
    6阶幻方:
      35   1   6 | 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   */
    void singleEven()
    {
        int temp;
        // 步骤一
        // A象限
        ox=oy=0;
        odd(n/2,pow(n/2,2)*0);
        // D象限
        ox=oy=n/2;
        odd(n/2,pow(n/2,2)*1);
        // B象限
        ox=n/2,oy=0;
        odd(n/2,pow(n/2,2)*2);
        // C象限
        ox=0,oy=n/2;
        odd(n/2,pow(n/2,2)*3);
        // 对已经按ADBC象限以奇阶方式填充的幻方做处理
        m=(n-2)/4;
        for(i=0;i<n/2;i++)
        {   
            // 步骤二
            for(j=0;j<m;j++)
            {
                k=(i==n/4)?n/4+j:j;
                temp=a[i][k];
                a[i][k]=a[i+n/2][k];
                a[i+n/2][k]=temp;
            }
            // 步骤三
            for(j=0;j<m-1;j++)
            {
                k=n/2+n/4+j;
                temp=a[i][k];
                a[i][k]=a[i+n/2][k];
                a[i+n/2][k]=temp;
            }
        }
    }
    /* 双偶阶幻方
    n为偶数,且能被4整除 (n=4,8,12,16,20……;n=4k,k=1,2,3,4,5……)
    互补:如果两个数字的和,等于幻方最大数和最小数的和,即 n*n+1,称为互补。*/
    /* 四阶幻方
    将数字从左到右、从上到下按顺序填写:
       1   2   3   4
       5   6   7   8
       9  10  11  12
      13  14  15  16
    将对角线上的数字,换成与它互补的数字。
    这里,n×n+1 = 4×4+1 = 17;
    把1换成17-1 = 16;
    把6换成17-6 = 11;
    把11换成17-11 = 6;
    把16换成17-16 = 1;
    ……
    换完后就是一个四阶幻方。
      16*  2   3  13*
       5  11* 10*  8
       9   7*  6* 12
       4* 14  15   1* */
    void FourXFour()
    {
        // 对已填写数字的4阶幻方进行对角线互补替换
        for(i=0;i<4;i++)
        {
            a[oy+i][ox+i]=total-a[oy+i][ox+i];
            a[oy+i][ox+(4-i-1)]=total-a[oy+i][ox+(4-i-1)];
        }
    }
    /* 对于n=4k阶幻方,我们先把数字按顺序填写。
       1   2   3   4   5   6   7   8
       9  10  11  12  13  14  15  16
      17  18  19  20  21  22  23  24
      25  26  27  28  29  30  31  32
      33  34  35  36  37  38  39  40
      41  42  43  44  45  46  47  48
      49  50  51  52  53  54  55  56
      57  58  59  60  61  62  63  64
    写好后,按4*4把它划分成k*k个方阵。
    因为n是4的倍数,一定能用4*4的小方阵分割。
       1   2   3   4 |  5   6   7   8
       9  10  11  12 | 13  14  15  16
      17  18  19  20 | 21  22  23  24
      25  26  27  28 | 29  30  31  32
    ---------------------------------
      33  34  35  36 | 37  38  39  40
      41  42  43  44 | 45  46  47  48
      49  50  51  52 | 53  54  55  56
      57  58  59  60 | 61  62  63  64
    然后把每个小方阵的对角线上的数字换成互补的数字,就构成幻方。
      64*  2   3  61*| 60*  6   7  57*
       9  55* 54* 12 | 13  51* 50* 16
      17  47* 46* 20 | 21  43* 42* 24
      40* 26  27  37*| 36* 30  31  33*
    ---------------------------------
      32* 34  35  29*| 28* 38  39  25*
      41  23* 22* 44 | 45  19* 18* 48
      49  15* 14* 52 | 53  11* 10* 56 
       8* 58  59   5*|  4* 62  63   1* */
    void doubleEven()
    {
        // 填写数字
        x=y=0;
        for(i=1;i<=pow(n,2);i++)
        {
            a[y][x]=i;
            if(i%n==0) x=0,y++;
            else x++;
        }
        total=1+pow(n,2);   // 最大数和最小数的和
        // 以 4x4 大小分割幻方
        m=n/4;
        x=y=0;
        ox=oy=0;
        for(k=1;k<=pow(m,2);k++)
        {
            // 对每个 4x4 幻方做对角互补替换
            FourXFour();
            if(k%m==0) ox=0,oy+=4;
            else ox=k%m*4;  // 转移到下一个 4x4 幻方
        }
    }
    

    Please input n(3<=n[<=17]): 3
    s=15
    8 1 6 =15
    3 5 7 =15
    4 9 2 =15
    Please input n(3<=n[<=17]): 5
    s=65
    17 24 1 8 15 =65
    23 5 7 14 16 =65
    4 6 13 20 22 =65
    10 12 19 21 3 =65
    11 18 25 2 9 =65
    Please input n(3<=n[<=17]):

    源程序略有点问题,我顺手修改了
    出处
    http://blog.csdn.net/cmutoo/article/details/5487157

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 C++使用Gunplot
  • ¥15 这个电路是如何实现路灯控制器的,原理是什么,怎么求解灯亮起后熄灭的时间如图?
  • ¥15 matlab数字图像处理频率域滤波
  • ¥15 在abaqus做了二维正交切削模型,给刀具添加了超声振动条件后输出切削力为什么比普通切削增大这么多
  • ¥15 ELGamal和paillier计算效率谁快?
  • ¥15 file converter 转换格式失败 报错 Error marking filters as finished,如何解决?
  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 关于#r语言#的问题:差异分析前数据准备,报错Error in data[, sampleName1] : subscript out of bounds请问怎么解决呀以下是全部代码:
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)