奥数九宫格怎么分析(奥数中九宫算升级版)

九宫算是指在3*3个方格中,每个方格分别放入1个数,这个数必须是1-9中之一,每个数必须而且只能放入一次。要求3*3方格中每一行、每一列、两条对角线的三个数之和都相等。

五阶幻方是指在5*5个方格中,每个方格各放入一个数,这个数必须是1-25中之一,每个数必须而且只能放入一次。要求5*5方格中每一行、每一列、两条对角线的五个数之和都相等。

原以为奇数阶幻方中,正中间的方格应该填入数列中的中位数,例如在3阶幻方中,正中间的方格应该填入9,但是在5阶幻方中,这个假设就失效了,下面是具体的例子。

奥数九宫格怎么分析(奥数中九宫算升级版)(1)

奥数九宫格怎么分析(奥数中九宫算升级版)(2)

正中间的单元格一个是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

    分享
    投诉
    首页