奇数用的是常用的斜线填数法
偶数的算法是:
当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
我写的程序:(比较傻的方法,因为昨天太晚了不想优化了:P)
include <stdio.h>
#define N 100
void 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)
getch()
}
void n1(int n)
{
int i,j,count=0,num[N][N]
for(i=0,j=(n-1)/2count<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=0i<ni++)
for(j=0j<nj++)
{
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=0i<ni++)
for(j=0j<nj++)
{
count++
num[i][j]=count
}
for(i=0i<n-1i++)
for(j=0j<n-1-ij++)
{
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=0i<ni++)
for(j=0j<nj++)
{
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)/2count<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+mcount<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+mcount<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)/2count<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=0i<mi++)
{
for(j=0j<v-1||j>n-v+1j++)
{
t=num[i][j]
num[i][j]=num[i+m][j]
num[i+m][j]=t
}
for(j=n-v+2j<nj++)
{
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=0i<ni++)
for(j=0j<nj++)
{
printf("%5d",num[i][j])
count++
if(count%n==0)
printf("\n")
}
}
具体做法:方法一;
/*此程序使我按照上面介绍的魔方阵的规律编写的,不过只能求奇数魔方阵,经过测试可以算到508阶*/
#define N 7
#include<stdio.h>
void main()
{
int a[N][N],i,j,k
for(i=0i<Ni++)/*先处理第一行*/
for(j=0j<Nj++)
{
a[i][j]=0/*先令所有元素都为0*/
}
j=(N-1)/2/*判断j的位置*/
a[0][j]=1 /*将1放在第一行中间一列*/
for(k=2k<=N*Nk++)/*再从2开始处理*/
{
i=i-1 /*存放的行比前一个数的行数减1*/
j=j+1 /*存放的列比前一个数的列数加1*/
if((i<0)&&(j==N))/*前一个数是第一行第N列时,把下一个数放在上一个数的下面*/
{
i=i+2
j=j-1
}
else
{
if(i<0)/*当行数减到第一行,返回到最后一行*/
i=N-1
if(j>N-1)/*当列数加到最后一行,返回到第一行*/
j=0
}
if(a[i][j]==0) /*如果该元素为0,继续执行程序*/
a[i][j]=k
else /*如果该元素不为0,就说明要填的数的位置已经被占,则该数放在上一个数的下面*/
{
i=i+2
j=j-1
a[i][j]=k
}
}
for(i=0i<Ni++)/*输出数组*/
{
for(j=0j<Nj++)
printf("%5d",a[i][j])
printf("\n\n")
}
}
方法二:
/*这个是网友qfyzy为帮助我找错而提供的,可以算到99阶*/
#define N 7
#include<stdio.h>
void main()
{
int a[N][N]={0},i=0,j,k/*先令所有元素都为0*/
j=(N-1)/2
i=0
for(k=1k<=N*N)/*开始处理*/
{
if((i<0)&&(j==N))/*前一个数是第一行第N列时,把下一个数放在上一个数的下面*/
{
i=i+2
j=j-1
}
else if(i<0)/*当行数减到第一行,返回到最后一行*/
i=N-1
else if(j>N-1)/*当列数加到最后一行,返回到第一行*/
j=0
else if(!a[i][j]){ /*如果该元素为0,继续执行程序*/
a[i][j]=k++
i=i-1
j=j+1
}
else /*如果该元素不为0,就说明要填的数的位置已经被占,则该数放在上一个数的下面*/
{
i=i+2
j=j-1
}
}
for(i=0i<Ni++)/*输出数组*/
{
for(j=0j<Nj++)
printf("%5d",a[i][j])
printf("\n\n")
}
}
魔方的计算公式是还原公式方法如下:
1、底棱归位,又称之为 Cross,英文的意思是十字还原,选择白色面做底面,在魔方的底层架十字。还原棱就是在每一个面上都拼出个十字,拼十字时不是按面来的,而是按层来的。先还第一层的,也就是在第一面上拼出个十字。
2、底角归位,就是复原魔方第一层四个角块。
3、第二层棱块归位,就是复原魔方中层四个棱块的步骤。
4、顶棱面位,也称顶部架十字,就是魔方四个顶棱块与顶面色相同的面全部调至顶面。在这一步里,还原步骤会在前面提到的4种情况里从左到右之间切换,也就是说,当遇到“点”的时候,做完动作后会是个“小拐弯”,然后再“一字”,最后才成“十字”。
5、顶角面位,就是使魔方的四个顶角的顶面色全部调至顶面。
6、顶棱归位,使已经面位的魔方四个顶棱的另一面的颜色和所在的另四个面的颜色同色。我们对好魔方顶层四个角的顺序的第6步也就完成了。
7、顶角归位,就是使已经面位的魔方四个顶角的其他两面颜色也和对应面所在的颜色同色。这个就是出现上面3种情况按步骤还原后仍不能还原整个魔方的6面,而是在上面的第一和第二种情况中出现情况间死循环,也就是出现情况一做完后变成情况二,出现情况二做完又变成情况一这样的死循环现象,这种特殊情况确实存在但很几率很小。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)