九宮算是指在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;
}
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!