输出魔方矩阵(C语言实现)

题目:
输出魔方阵,所谓魔方阵是指这样的方阵,它的每一行,每一列和对角线的和均相等,要输出1-n^2个自然数构成的魔方阵,例如
8 1 6
3 5 7
4 9 2

解决方案

  1. 当n<=2时不存在魔方矩阵
	if(n<3){
        printf("不存在n=%d的魔方矩阵",n);
        return;
    }
  1. 当n为奇数时,可用“罗泊法”即

⑴将1放在第一行中间一列;
⑵从2开始直到n×n止各数依次按下列规则存放;每一个数存放的行比前一个数的行数减1,列数加1(例如上面的三阶魔方阵,5在4的上一行后一列);
⑶如果上一个数的行数为1,则下一个数的行数为n(指最下一行);例如1在第一行,则2应放在最下一行,列数同样加1;
⑷当上一个数的列数为n时,下一个数的列数应为1,行数减去1。例如2在第3行最后一列,则3应放在第二行第一列;
⑸如果按上面规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。例如按上面的规定,4应该放在第1行第2列,但该位置已经被占据,所以4就放在3的下面。

	if(n%2==1){
        int count=1;
        int i=0,j=n/2;
        a[i][j]=count++;
        for(int temp=0;temp<n*n-1;temp++){
            if(a[(i-1+n)%n][(j+1+n)%n]!=0)
                i=(i+1+n)%n;
            else{
                i=(i-1+n)%n;
                j=(j+1+n)%n;
            }
            a[i][j]=count++;
        }      
    }

3.当n为偶数时,又分为两种情况,即n能否被4整除

当n能被4整除时,方案如下

(1) 先将整个方阵划分成k*k个4阶方阵,然后在每个4阶方阵的对角线上做记号;
(2) 由左而右、由上而下,遇到没有记号的位置才填数字,但不管是否填入数字,每移动一格数字都要加1;
(3) 自右下角开始,由右而左、由下而上,遇到没有数字的位置就填入数字,但每移动一格数字都要加1。

	if(n%4==0){
        int num=n/4;
        for(int i=0;i<num;i++)
            for(int j=0;j<num;j++){
                a[4*i+0][4*j+0]=-1;
                a[4*i+0][4*j+3]=-1;
                a[4*i+1][4*j+1]=-1;
                a[4*i+1][4*j+2]=-1;
                a[4*i+2][4*j+1]=-1;
                a[4*i+2][4*j+2]=-1;
                a[4*i+3][4*j+0]=-1;
                a[4*i+3][4*j+3]=-1;
            }
        int count=1;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(a[i][j]==0)
                    a[i][j]=count++;
        for(int i=n-1;i>=0;i--)
            for(int j=n-1;j>=0;j--)
                if(a[i][j]==-1)
                    a[i][j]=count++;
        
    }

当n不能被4整除时,方案如下

填制魔方阵时,先将整个方阵划成田字型的四个2 k + 1阶的奇数阶小方阵,并以下法做注记:
(1)右半两个小方阵中大于k+2的列;
(2)左半两个小方阵中( k + 1 , k + 1 )的格位;
(3)左半两个小方阵中除了( k+1 , 1 )是指第一列第k+1行的格位之外,小于k +1的列。
以奇数阶魔方阵的方法连续填制法依左上、右下、右上、左下的顺序分别填制这四个小方阵。将上半及下半方阵中有注记的数字对调,魔方阵完成。

	if(n%4==2){
        int num=n/2;
        int count=1;
        int sym=1,x=0,y=0;
        while(sym!=0){
            int i=0,j=num/2;
            a[i+x][j+y]=count++;
            for(int temp=0;temp<num*num-1;temp++){
                if(a[(i-1+num)%num+x][(j+1+num)%num+y]!=0)
                    i=(i+1+num)%num;
                else{
                    i=(i-1+num)%num;
                    j=(j+1+num)%num;
                }
                a[i+x][j+y]=count++;
            }
            switch(sym){
                case 1:x+=num; y+=num; sym=2; break;
                case 2:x-=num; sym=3; break;
                case 3:x+=num; y-=num; sym=4; break;
                case 4:sym=0; break;
            }      
        }
        
        int k=(n-2)/4;
        for(int j=num+k+2;j<n;j++){  //1
            for(int i=0;i<num;i++){
                int temp=a[i][j];
                a[i][j]=a[i+num][j];
                a[i+num][j]=temp;
            }
        }
        int temp=a[k][k]; a[k][k]=a[k+num][k]; a[k+num][k]=temp;  //2
        for(int j=0;j<k;j++)
            for(int i=0;i<num;i++)
                if(i!=k){
                    int temp=a[i][j];
                    a[i][j]=a[i+num][j];
                    a[i+num][j]=temp;
                }
                
    }

运行结果如下

n=10
n=10
n=8
n=8
n=9
n=9

完整代码示例

void function4(int n){//魔方矩阵
    int a[100][100];
    memset(a,0,sizeof(a));
    if(n<3){
        printf("不存在n=%d的魔方矩阵",n);
        return;
    }
    if(n%2==1){
        int count=1;
        int i=0,j=n/2;
        a[i][j]=count++;
        for(int temp=0;temp<n*n-1;temp++){
            if(a[(i-1+n)%n][(j+1+n)%n]!=0)
                i=(i+1+n)%n;
            else{
                i=(i-1+n)%n;
                j=(j+1+n)%n;
            }
            a[i][j]=count++;
        }      
    }
    if(n%4==0){
        int num=n/4;
        for(int i=0;i<num;i++)
            for(int j=0;j<num;j++){
                a[4*i+0][4*j+0]=-1;
                a[4*i+0][4*j+3]=-1;
                a[4*i+1][4*j+1]=-1;
                a[4*i+1][4*j+2]=-1;
                a[4*i+2][4*j+1]=-1;
                a[4*i+2][4*j+2]=-1;
                a[4*i+3][4*j+0]=-1;
                a[4*i+3][4*j+3]=-1;
            }
        int count=1;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(a[i][j]==0)
                    a[i][j]=count++;
        for(int i=n-1;i>=0;i--)
            for(int j=n-1;j>=0;j--)
                if(a[i][j]==-1)
                    a[i][j]=count++;
        
    }
    if(n%4==2){
        int num=n/2;
        int count=1;
        int sym=1,x=0,y=0;
        while(sym!=0){
            int i=0,j=num/2;
            a[i+x][j+y]=count++;
            for(int temp=0;temp<num*num-1;temp++){
                if(a[(i-1+num)%num+x][(j+1+num)%num+y]!=0)
                    i=(i+1+num)%num;
                else{
                    i=(i-1+num)%num;
                    j=(j+1+num)%num;
                }
                a[i+x][j+y]=count++;
            }
            switch(sym){
                case 1:x+=num; y+=num; sym=2; break;
                case 2:x-=num; sym=3; break;
                case 3:x+=num; y-=num; sym=4; break;
                case 4:sym=0; break;
            }      
        }
        
        int k=(n-2)/4;
        for(int j=num+k+2;j<n;j++){  //1
            for(int i=0;i<num;i++){
                int temp=a[i][j];
                a[i][j]=a[i+num][j];
                a[i+num][j]=temp;
            }
        }
        int temp=a[k][k]; a[k][k]=a[k+num][k]; a[k+num][k]=temp;  //2
        for(int j=0;j<k;j++)
            for(int i=0;i<num;i++)
                if(i!=k){
                    int temp=a[i][j];
                    a[i][j]=a[i+num][j];
                    a[i+num][j]=temp;
                }
                
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
            printf("%3d ",a[i][j]);
        printf("\n");
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值