魔方算法

奇数用的是常用的斜线填数法 



偶数的算法是:

当n为4的倍数时:采用对称元素交换法。首先把数1-n^2按行从上至下,从左至右填人方阵的n×n格。然后,把方阵的所有4 ×4子方阵中的两对角线上位置上的数固定下来不动;所有其它位置上的数关于方阵中心作对称交换,也就是把元素a(i,j)与元素a(n+1-i,n+ 1-j)的值交换。



当n为非4倍数的偶数(即4m+2形)时:首先把大方阵分解为4个奇数(2m+1阶)子方阵。上述奇数阶魔方给分解的4个子方阵对应赋值,上左子方最小(i),下右子次小(i+v),下左子方最大(i+3v),上右子方次大(i+2v),即4个子方阵对应元素相差v,其中v=n*n/4,然后作相应的元素交换:

a(i,j)与a(i+u,j)在同一列做对应交换(j<t或j>n-t+2)

a(t,1)与a(t+u,1);a(t,t)与a(t+u,t)两对元素交换

其中u=n/2,t=(n+2)/4

 

 

 

#include <stdio.h>
#define N 100

int main()
{
    void n1(int n);
    void n2(int n);
    void n3(int n);
    int n;
    printf("please input n:");
    scanf("%d",&n);
    printf("/n");
    if((n%2)!=0)
    n1(n);
    else if((n%4)==0)
    n2(n);
    else
    n3(n);
    getchar();
    return 0;
}

void n1(int n)
{
     int i,j,count=0,num[N][N];
     for(i=0,j=(n-1)/2;count<n*n;)
     {
         count++;
         num[i][j]=count;
         if(count%n==0)
         {
            i++;
         }
         else
         {
            i--;
            j++;
         }
         if(i<0)
            i+=n;
         if(j>=n)
            j-=n;
     }
     count=0;
     for(i=0;i<n;i++)
         for(j=0;j<n;j++)
         {
             printf("%5d",num[i][j]);
             count++;
             if(count%n==0)
                printf("/n");
         }
}

void n2(int n)
{
     int t,i,j,count=0,num[N][N];
     for(i=0;i<n;i++)
     for(j=0;j<n;j++)
     {
     count++;
     num[i][j]=count;
     }
     for(i=0;i<n-1;i++)
     for(j=0;j<n-1-i;j++)
     {
     if(i!=j)
     {
     t=num[i][j];
     num[i][j]=num[n-1-i][n-1-j];
     num[n-1-i][n-1-j]=t;
     }
     }
     count=0;
     for(i=0;i<n;i++)
     for(j=0;j<n;j++)
     {
     printf("%5d",num[i][j]);
     count++;
     if(count%n==0)
     printf("/n");
     }
}

void n3(int n)
{
     int i,j,m,t,v,count=0,num[N][N];
     v=(n+2)/4;
     m=n/2;
     for(i=0,j=(m-1)/2;count<m*m;)
     {
     count++;
     num[i][j]=count;
     if(count%m==0)
     i++;
     else
     {
     i--;
     j++;
     }
     if(i<0)
     i+=m;
     if(j>=m)
     j-=m;
     }
     for(i=m,j=(m-1)/2+m;count<2*m*m;)
     {
     count++;
     num[i][j]=count;
     if(count%m==0)
     i++;
     else
     {
     i--;
     j++;
     }
     if(i<m)
     i+=m;
     if(j>=2*m)
     j-=m;
     }
     for(i=0,j=(m-1)/2+m;count<3*m*m;)
     {
     count++;
     num[i][j]=count;
     if(count%m==0)
     i++;
     else
     {
     i--;
     j++;
     }
     if(i<0)
     i+=m;
     if(j>=2*m)
     j-=m;
     }
     for(i=m,j=(m-1)/2;count<4*m*m;)
     {
     count++;
     num[i][j]=count;
     if(count%m==0)
     i++;
     else
     {
     i--;
     j++;
     }
     if(i<m)
     i+=m;
     if(j>=m)
     j-=m;
     }
     for(i=0;i<m;i++)
     {
     for(j=0;j<v-1||j>n-v+1;j++)
     {
     t=num[i][j];
     num[i][j]=num[i+m][j];
     num[i+m][j]=t;
     }
     for(j=n-v+2;j<n;j++)
     {
     t=num[i][j];
     num[i][j]=num[i+m][j];
     num[i+m][j]=t;
     }
     }
     t=num[v-1][0];
     num[v-1][0]=num[v+m-1][0];
     num[v+m-1][0]=t;
     t=num[v-1][v-1];
     num[v-1][v-1]=num[v+m-1][v-1];
     num[v+m-1][v-1]=t;
     count=0;
     for(i=0;i<n;i++)
     for(j=0;j<n;j++)
     {
     printf("%5d",num[i][j]);
     count++;
     if(count%n==0)
     printf("/n");
     }
}

 

 

转自http://zhidao.baidu.com/question/45446632.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值