求解幻方问题
幻方是一种古老的数学游戏。n阶幻方就是把整数1~n2排成n×n的方阵,使得每行中的各元素之和,每列中的各元素之和,以及两条对角线上的元素都是同一个数S,S称为幻方的幻和。在中世纪的欧洲,对幻方有某种神秘的观念,许多人佩戴幻方以图避邪。奇数阶幻方的构造方法很简单,我们先来看一个三阶幻方,如图所示:
各数在方阵中的位置可以这样确定:
首先把1放在最上一行正中间的方格中,然后把下一个整数放置到右上方,如果到达最上一行,下一个整数放在最后一行,就好像它在第一行的上面,如果到达最右端,则下一整数放在最左端,就好像它在最右一列的右侧,当到达的方格中已填上数值时,下一个整数就放在刚填上数码的方格的正下方。照着三阶幻方,从1至9走一下,就可以明白它的构造方法,下面是程序:
#define
MAX 15
#include < stdio.h >
void main( void )
{
int m,mm,i,j,k,ni,nj;
int magic[MAX][MAX];
printf( " Enter the number you wanted\n " );
scanf( " %d " , & m);
for (i = 0 ;i < m;i ++ ) // 初始化
for (j = 0 ;j < m;j ++ )
magic[i][j] = 0 ;
if ((m > 0 ) && (m % 2 != 0 )) // 奇数阶
{
mm = m * m;
i = 0 ; // 第一个值的位置
j = m / 2 ;
for (k = 1 ;k <= mm;k ++ )
{
magic[i][j] = k;
// 求右上方方格的坐标
if (i == 0 ) // 最上一行
ni = m - 1 ; // 下一个位置在最下一行
else
ni = i - 1 ;
if (j == m - 1 ) // 最右端
nj = 0 ; // 下一个位置在最左端
else
nj = j + 1 ;
// 判断右上方方格是否已有数
if (magic[ni][nj] == 0 ) // 右上方无值
{
i = ni;
j = nj;
}
else // 右上方方格已填上数
i ++ ;
}
for (i = 0 ;i < m;i ++ )
{
for (j = 0 ;j < m;j ++ )
printf( " %4d " ,magic[i][j]);
printf( " \n " );
}
}
else // m<=0或m_是偶数
printf( " Error in input data.\n " );
}
以输入值5为例,程序的运行结果为:
#include < stdio.h >
void main( void )
{
int m,mm,i,j,k,ni,nj;
int magic[MAX][MAX];
printf( " Enter the number you wanted\n " );
scanf( " %d " , & m);
for (i = 0 ;i < m;i ++ ) // 初始化
for (j = 0 ;j < m;j ++ )
magic[i][j] = 0 ;
if ((m > 0 ) && (m % 2 != 0 )) // 奇数阶
{
mm = m * m;
i = 0 ; // 第一个值的位置
j = m / 2 ;
for (k = 1 ;k <= mm;k ++ )
{
magic[i][j] = k;
// 求右上方方格的坐标
if (i == 0 ) // 最上一行
ni = m - 1 ; // 下一个位置在最下一行
else
ni = i - 1 ;
if (j == m - 1 ) // 最右端
nj = 0 ; // 下一个位置在最左端
else
nj = j + 1 ;
// 判断右上方方格是否已有数
if (magic[ni][nj] == 0 ) // 右上方无值
{
i = ni;
j = nj;
}
else // 右上方方格已填上数
i ++ ;
}
for (i = 0 ;i < m;i ++ )
{
for (j = 0 ;j < m;j ++ )
printf( " %4d " ,magic[i][j]);
printf( " \n " );
}
}
else // m<=0或m_是偶数
printf( " Error in input data.\n " );
}
Enter the number you wanted
5
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9