奥数九宫格怎么分析(奥数中九宫算升级版)
九宫算是指在3*3个方格中,每个方格分别放入1个数,这个数必须是1-9中之一,每个数必须而且只能放入一次。要求3*3方格中每一行、每一列、两条对角线的三个数之和都相等。
五阶幻方是指在5*5个方格中,每个方格各放入一个数,这个数必须是1-25中之一,每个数必须而且只能放入一次。要求5*5方格中每一行、每一列、两条对角线的五个数之和都相等。
原以为奇数阶幻方中,正中间的方格应该填入数列中的中位数,例如在3阶幻方中,正中间的方格应该填入9,但是在5阶幻方中,这个假设就失效了,下面是具体的例子。
正中间的单元格一个是10,一个是9,都不是13。
下面的这个例子是从网上找到的五阶幻方求解的源程序,采用逐步搜索的方法,求得所有解。我最长运行了3小时,求得了大约29万种不同解,不知道全部有效解一共是多少?
#include "stdio.h"
#define LENGTH 10
#define SIZE LENGTH*LENGTH
int a[LENGTH][LENGTH],b[SIZE],degree,number=0,max,sum;
int main()
{
int i=0,j=0,m,temp,n,x,k,y,h,z;
printf("please input a degree:");
scanf("%d",°ree);
max=degree*degree;
sum=(max 1)*degree/2;
for(i=1;i<=degree;i )
{
b[i]=0;
//1-5标记为没有选中,因为0不是目标数字,所以i从1开始
//b[]可能代表某一行的5个数
for(j=0;j<degree;j )
{
a[i-1][j]=0;
//目标数组全部置为0,行标从0开始,列标也从0开始
}
}
//全部赋0值
i=j=z=0;
while(1)
//大循环开始
{
temp=a[i][j];
a[i][j]=0;
//把a[i][j]读出来,赋值给temp,然后将a[i][j]置为0
//a[][]为目标数组
for(m=temp 1 z,z=0;m<=max;m )
{
if(b[m]==0)
{
if(temp!=0)
{
b[temp]=0;
temp=0;
}
if(i<degree-2 && j<degree-2)
//是否进入第三行、第三列
{
if(i==degree-3)
//行判断,是不是第三行
{
for(n=0,x=0;n<i;n )
{
x =a[n][j];
}
x =m;
//x为已知数的和
k=sum-x;
//K为剩余数的和
if(k>max max-1 || (k==max max-1 && (b[max]==1 || b[max-1]==1)))
//剩余的数字已无可能
{
continue;
}
if(k<3 || (k==3 && (b[1]==1 && b[2]==1)))
//剩余的数字已无可能
{
m=max 1;
break;
}
}
if(j==degree-3)
//列判断,是不是第三列
{
for(n=0,x=0;n<j;n )
{
x =a[i][n];
//x为该行已选数字之和
}
x =m;
//m为该行第三列待选数字
k=sum-x;
//某列已选好的数字求和,没选的数字求和
if(k>max max-1 || (k==max max-1 && (b[max]==1 || b[max-1]==1)))
//还剩2个数没有选,如果k值大于最大两个数之和,表示没有可能;如果等于最大两个数之和,但是最大两个数其中之一已经用过了,表示没有可能。
{
continue;
}
if(k<3 || (k==3 && (b[1]==1 && b[2]==1)))
//最小情况判断,比3还小不可能,等于3但是1,2其中之一已被选择,也不可能
{
m=max 1;
break;
}
}
//将M赋值给数组a,同时标记数组b,该数字已使用
a[i][j]=m;
b[m]=1;
j ;
break;
}
if(j==degree-2)
//该行已经选了3个数,准备选第四个数
{
for(n=0,x=0;n<j;n )
{
x =a[i][n];
//前面的数求和
}
x =m;
//和值加入dm
k=sum-x;
//剩余的值
if(k>0 && k<=max && m!=k && b[k]==0)
//剩余的值在最大和最小之间,m与k不相等,k值没有被选过
{
a[i][j]=m;
b[m]=1;
a[i][j 1]=k;
b[k]=1;
//最后2个数字,一起完成赋值
if(i<degree-2)
//如果还剩超过2行,则进入下一行
{
i ;
j=0;
break;
}
}
else
{
if(i==degree-2 && j==1)
{
j--;
b[a[i 1][j]]=0;
a[i 1][j]=0;
break;
}
else
{
continue;
}
}
}
if(i==degree-2)
{
//还剩2行
for(n=0,x=0;n<i;n )
{
x =a[n][j];
}
x =m;
k=sum-x;
//前几行求和,另外得出剩下几行的和
if(k>0 && k<=max && m!=k && b[k]==0)
{
//k的值在最大]、最小之间,m、k对应的值没有被用过
if(j<degree-2)
{
if(j==0)
{
for(n=0,x=degree-1,y=0;n<i;n )
{
y =a[n][x--];
//对角线求和
}
y =k;
h=sum-y;
//对角线已选值的和,以及剩余的值的和
if(h>0 && h<=max && h!=k && h!=m && b[h]==0)
{
//对角线的判断
a[i][j]=m;
b[m]=1;
a[i 1][j]=k;
b[k]=1;
z=h-1;
//该行,和下一行的值复制
j ;
break;
}
else
{
continue;
}
}
if(j==1)
{
for(n=0,x=degree-1,y=0;n<i;n )
{
y =a[n][x--];
}
y =(a[degree-1][0] m);
if(y!=sum)
{
//值不满足65,重新归零
b[a[degree-1][0]]=0;
a[degree-1][0]=0;
j--;
break;
}
}
a[i][j]=m;
b[m]=1;
a[i 1][j]=k;
b[k]=1;
j ;
break;
}
else if(j==degree-2)
{
for(n=0,x=0;n<=i;n )
{
x =a[n][n];
}
h=sum-x;
if(h>0 && h<=max && h!=m && h!=k && b[h]==0)
{
for(n=0,y=0;n<=j;n )
{
y =a[n][degree-1];
}
if(y==x)
{
for(n=0,y=0;n<i;n )
{
y =a[degree-1][n];
}
y =k;
if(y==x)
{
a[i 1][j]=k;
b[k]=1;
a[i][j]=m;
b[m]=1;
a[ i][ j]=h;
b[h]=1;
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
b[a[i][j 1]]=0;
a[i][j 1]=0;
b[a[i][j]]=0;
a[i][j]=0;
if(j==1)
{
b[a[i 1][j-1]]=0;
a[i 1][j-1]=0;
j--;
break;
}
else
{
continue;
}
}
}
}
else
{
if(j==1)
{
//这个判断好像无效
if(j==degree-2)
{
b[a[i][j 1]]=0;
a[i][j 1]=0;
}
b[a[i][j]]=0;
a[i][j]=0;
j--;
b[a[i 1][j]]=0;
a[i 1][j]=0;
break;
}
if(j==degree-2)
{
b[a[i][j]]=0;
a[i][j]=0;
b[a[i][j 1]]=0;
a[i][j 1]=0;
//某列两个数值归0
}
continue;
}
}
if(i==degree-1 && j==degree-1)
{
//已经到达第5行、第五列
for(k=0;k<degree;k )
{
for(h=0;h<degree;h )
{
//满足条件的结果输出
printf("M",a[k][h]);
}
printf("\n");
}
printf("\n");
number ;
printf("num=]\n",number);
if(number==100)
{
getchar();
getchar();
}
for(k=degree-2;k<degree;k )
{
for(h=1;h<degree;h )
{
b[a[k][h]]=0;
a[k][h]=0;
//第四行、第五行归0
}
}
b[a[degree-1][0]]=0;
a[degree-1][0]=0;
//第五行第一列归0
i--;
j=0;
break;
}
}
}
if(m>max)
{
//超出理论范围
if(temp!=0)
{
b[temp]=0;
}
if(j==0 && i>0)
{
i--;
j=degree-1;
b[a[i][j]]=0;
a[i][j]=0;
j--;
}
else if(j>0)
{
j--;
b[a[i 1][j]]=0;
a[i 1][j]=0;
}
else if(i==0 && j==0)
{
break;
}
}
}
printf("the total number is %d\n",number);
//结果输出
return 0;
}
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com