蓝颜色字是原创
今天看的是关于幻方的东西,我在一个Q群里提了这个问题,别人都不屑说的,无奈的我只好自己去找资料,自己写程序。觉得这样学到点东西,不过那些算法都是在网上找的,我的工作是学习算法以及用代码实现它。(不知道这样对于学习算法有效果不?希望ACMER牛人知道下哈~~谢了先~~)(我也不知道对不对,只是测试了很简单的数据,希望大牛们看到指教下,谢了先)
对于奇数阶:
罗伯法的具体方法如下:
把1(或最小的数)放在第一行正中;
按以下规律排列剩下的n2-1个数:
1)每一个数放在前一个数的右上一格;
2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
4)如果这个数所要放的格已经超出了顶行且超出了最右列那么就把它放在前一个数的下一行同一列的格内;
5)如果这个数所要放的格已经有数填入,处理方法同4)。
自己写的奇数阶的幻方程序
#include<stdio.h>
#define MAX 101
void main()
{
int a[MAX][MAX],i,j,n,o,p;
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[i][j]=0;
o=0;
p=(n-1)/2;
a[o][p]=1; //对1单独处理
for(i=2;i<=n*n;i++)
{
o--;
p++; //对应步骤1
if(o==-1&&p==n)
{
o=o+2;
p--; //对应步骤4
}
if(o==-1)
o=n+o; //对应步骤2
if(p==n)
p=p-n; //对应步骤3
if(a[o][p]!=0)
{
o=o+2;
p--;
} //对应步骤5
a[o][p]=i;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%3d/t",a[i][j]);
printf("/n");
} //打印幻方
}
对于偶数阶:
偶数阶幻方填法!
前面有奇数阶幻方填法,下面以4阶为例,说说偶数阶的填法:
首先,按顺序写下16个数:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
接下来固定对角线上数字不动(这里是1、6、11、16和4、7、10、13),其它数字作左右对换,如2与3换,5与8换等,得到下面的排列:
1 3 2 4
8 6 7 5
12 10 11 9
13 15 14 16
继续固定对角线,其他数字作上下对称变换,如8与12换,2与15换等,得到如下排列:
1 15 14 4
12 6 7 9
8 10 11 5
13 3 2 16
这就是四阶幻方,每行每列四个数字之和均为34,其他偶数阶幻方填法可类推!
这是我写的偶数阶幻方的程序
#include<stdio.h>
#define MAX 100
void main()
{
int a[MAX][MAX],i,j,n,temp;
scanf("%d",&n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[i][j]=i*n+j+1; //对应步骤1
for(i=0;i<n;i++)
for(j=0;j<n/2;j++)
{
if(i!=j&&(i+j)!=(n-1))
{
temp=a[i][j];
a[i][j]=a[i][n-1-j];
a[i][n-1-j]=temp;
}
} //对应步骤2
for(j=0;j<n/2;j++)
for(i=0;i<n;i++)
{
if(i!=j&&(i+j)!=(n-1))
{
temp=a[j][i];
a[j][i]=a[n-1-j][i];
a[n-1-j][i]=temp;
}
} //对应步骤3
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%d/t",a[i][j]);
printf("/n"); //打印幻方
}
}