Ⅰ 如何用c語言編寫幻方多謝回答
//分析:魔方陣有如下規律:
// 1:自然數1總是在方陣第一行當中一列上。
// 2:後續的自然數在當前數的右上方,
// 1)如果是在第一行則行數變為第n行列數加1 ;
// 2)如果是在最後一列,行數減1,列數為第1行。
// 3)如果後續的數所處位置已有數,則行數加1,列數不變。
/******************************************************************************************************************************
巧填奇數階幻方(魔方陣)[轉]2007-01-03 17:57 一、什麼叫幻方?
(通俗點說)把一些有規律的數填在縱橫格數都相等的正方形圖內,使每一行、每一列和每一條對角線上各個數之和都相等。這樣的方陣圖叫做幻方。
幻方又分為奇數階幻方和偶數階幻方。奇數階幻方是指橫行、豎列都是單數(即3、5、7、9……)的方陣圖。偶數階幻方是指橫行、豎列都是雙數(即4、6、8、10……)的方陣圖。
二、奇數階幻方的填法。
奇數階幻方中最簡便的一種就是三階幻方,又稱「九宮圖」。
平常我們遇到這類題都是用分析、分組、嘗試的方法推出,這種方法較麻煩,如果是五階幻方、七階幻方就更困難了。
有一種方法不僅能很快地填出三階幻方,還能很快地填出五階幻方、七階幻方、九階幻方……那就是「口訣法」
口 訣
「1」坐邊中間,斜著把數填;
出邊填對面,遇數往下旋;
出角僅一次,轉回下格間。
注意:
(1)這里的「1」,是指要填的這一列數中的第一個數。
(2)「1」坐邊中間,指第一個數要填在任何一邊的正中間的空格里。
(3)從1到2時,必須先向邊外斜(比如:第一個數填在上邊的正中間,填第二個數時,要向左上方或右上方斜),填後面的數時也要按照同樣的方向斜。
*******************************************************************************************************************************/
#include<iostream>
using namespace std;
void main()
{
int a[32][32],i,j,k,p,n;
p=1;
while(p==1)
{
cout<<"Enter n(n=1~25):";
cin>>n;
if((n!=0)&&(n<=25)&&(n%2!=0))
p=0;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j]=0;
j=n/2+1;
a[1][j]=1;
for(k=2;k<=n*n;k++)
{
i=i-1;
j=j+1;
if((i<1)&&(j>n))
{
i=i+2;
j=j-1;
}
else
{
if(i<1)
i=n;
if(j>n)
j=1;
}
if(a[i][j]==0)
a[i][j]=k;
else
{
i=i+2;
j=j-1;
a[i][j]=k;
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
}
/*C_ban*
所謂的魔方距陣就是一種特殊的奇數階方陣:它的行,列,對角線,上的數字之和都要相等,且方陣中的每一個數字都不相等,且數字的范圍都在1到n*n之間.
我編的程序如下:
*/
#include<stdio.h>
#define N 15
main()
{
int i,j,row,cloum,size,square[N][N],count;
clrscr();
printf("please enter the square size(odd && <=15):\n");
scanf("%d",&size);
while(size%2==0||size>15||size<3)
{
printf("error e to the wrng input!please input it again!\n");
scanf("%d",&size);
}
for(i=0;i<size;i++)
for(j=0;j<size;j++)
square[i][j]=0;
i=0;j=(size-1)/2;
square[i][j]=1;
for(count=2;count<=size*size;count++)
{
row=i-1<0?(size-1):(i-1);
cloum=j-1<0?(size-1):(j-1);
if(square[row][cloum])
i=(++i)%size;
else
{i=row;
j=j-1<0?(size-1):(j-1);
}
square[i][j]=count;
}
printf("the %d square is:\n",size);
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
printf("%d",square[i][j]);
printf("\n");
}
}
只能求奇數的魔方陣
#define N 20
main()
{
int a[N][N];
int n,i,j,r;
scanf("%d",&n);
for(i=0;i<N;i++) for(j=0;j<N;j++) a[i][j]=0;
i=0;
j=n/2;
a[i][j]=1;
for (r=2;r<=n*n;r++)
if (a[(i+n-1)%n][(j+1)%n]==0)
{i=(i+n-1)%n;j=(j+1)%n;a[i][j]=r;}
else
{i=(i+1)%n;a[i][j]=r;}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++) printf("%4d",a[i][j]);
printf("\n");
}
}
這是以前別人寫的,你參考一下!
Ⅱ 高手們,幫忙啊,c語言程序設計
*問題分析與演算法設計
最簡單的演算法是:採用窮舉法,設定4X4矩陣中每一個元素的值後,判斷每一行、每一列和兩條對角線上的4個數字組成的四位數是否都是可逆素數,若是則求出了滿足題意的一個解。
這種演算法在原理是對的,也一定可以求出滿足題意的全部解。但是,按照這一思路編出的程序效率很低,在微機上幾個小時也不會運行結束。這一演算法致命的缺陷是:要窮舉和判斷的情況過多。
充分利用題目中的「每一個四位數都是可逆素數」這一條件,可以放棄對矩陣中每個元素進行的窮舉的演算法,先求出全部的四位可逆素數(204個),以矩陣的行為單位,在四位可逆素數的范圍內進行窮舉,然後將窮舉的四位整數分解為數字後,再進行列和對角線方向的條件判斷,改進的演算法與最初的演算法相比,大大地減少了窮舉的次數。
考慮矩陣的第一行和最後一行數字,它們分別是列方向四位數的第一個數字和最後一個數字,由於這些四位數也必須是可逆素數,所以矩陣的每一行和最後一行中的各個數字都不能為偶數或5。這樣窮舉矩陣的第一行和最後一行時,它們的取值范圍是:所有位的數字均不是偶數或5的四位可逆數。由於符合這一條件的四位可逆素數很少,所以這一范圍限制又一次減少了窮舉的次數。
對演算法的進一步研究會發現:當設定了第一和第二行的值後,就已經可以判斷出當前的這種組合是否一定是錯誤的(尚不能肯定該組合一定是正確的)。若按列方向上的四個兩位數與四位可逆數的前兩位矛盾(不是其中的一種組合),則第一、二行的取值一定是錯誤的。同理在設定了前三行數據後,可以立刻判斷出當前的這種組合是否一定是錯誤的,若判斷出矛盾情況,則可以立刻設置新的一組數據。這樣就可以避免將四個數據全部設定好以後再進行判斷所造成的低效。
根據以上分析,可以用偽語言描述以上改進的演算法:
開始
找出全部四位的可逆素數;
確定全部出現在第一和最後一行的四位可逆素數;
在指定范圍 內窮舉第一行
在指定范圍內窮舉第二行
若第一、第二、三行已出現矛盾,則繼續窮舉下一個數;
在指定范圍內窮舉第四行
判斷列和對角方向是否符合題意
若符合題意,則輸出矩陣;
否則繼續窮舉下一個數;
結束
在實際編程中,採用了很多程序設計技巧,假如設置若干輔助數組,其目的就是要最大限度的提高程序的執行效率,縮短運行時間。下面的程序運行效率是比較高的。
*程序說明與注釋
#include<stdio.h>
#include<math.h>
int number[210][5]; /*存放可逆素數及素數分解後的各位數字*/
int select[110]; /*可以放在矩陣第一行和最後一行的素數的下標*/
int array[4][5]; /*4X4的矩陣,每行0號元素存可逆素數對應的數組下標*/
int count; /*可逆素數的數目*/
int selecount; /*可以放在矩陣第一行和最後一行的可逆素數的數目*/
int larray[2][200]; /*存放素數前二、三位數的臨時數組所對應的數量計數器*/
int lcount[2];
int num(int number);
int ok(int number);
void process(int i);
void _num(int i);
int comp_num(int n);
int find1(int i);
int find2(void);
int find0(int num);
void p_array(void);
int main()
{
int i,k,flag,cc=0,i1,i4;
printf("there are magic squares with invertable primes as follw:\n");
for(i=1001;i<9999;i+=2) /*求滿足條件的可逆素數*/
{
k=i/1000;
if(k%2!=0&&k!=5&&num(i)) /*若可逆素數的第一位不是偶數或5*/
{
number[count][0]=i; /*存入數組*/
process(count++); /*分解素數的各位數字*/
if(number[count-1][2]%2!=0&& /*若可逆素數滿足放在矩陣第一行*/
number[count-1][3]%2!=0&& /*和最後一行的條件,記錄可逆素數的*/
number[count-1][2]!=5&& /*下標,計數器加1*/
number[count-1][3]!=5)
select[selecount++]=count-1;
}
}
larray[0][lcount[0]++]=number[0][0]/100; /*臨時數組的第一行存前二位*/
larray[1][lcount[1]++]=number[0][0]/10; /*臨時數組的第二行存前三位*/
for(i=1;i<count;i++) /*將素數不重復的前二、三位存入臨時數組中*/
{
if(larray[0][lcount[0]-1]!=number[i][0]/100)
larray[0][lcount[0]++]=number[i][0]/100;
if(larray[1][lcount[1]-1]!=number[i][0]/10)
larray[1][lcount[1]++]=number[i][0]/10;
}
for(i1=0;i1<selecount;i1++) /*在第一行允許的匯聚圍內窮舉*/
{
array[0][0]=select[i1]; /*取對應的素數下標*/
_num(0); /*復制分解的素數*/
for(array[1][0]=0;array[1][0]<count;array[1][0]++) /*窮舉第二行*/
{
_num(1); /*復制分解的數字*/
if(!comp_num(2))
continue; /*若每列的前兩位的組成與素數相矛盾,則試探下一個數*/
for(array[2][0]=0;array[2][0]<count;array[2][0]++) /*窮舉第三行*/
{
_num(2); /*復制分解的數字*/
if(!comp_num(3))
continue; /*若每列的前三位的組成與素數相矛盾,則試探下一個數*/
for(i4=0;i4<selecount;i4++) /*在最後一行允許的范圍內窮舉*/
{
array[3][0]=select[i4];
_num(3); /*復制分解的數字*/
for(flag=1,i=1;flag&&i<=4;i++) /*判斷每列是否可逆素數*/
if(!find1(i))flag=0;
if(flag&&find2()) /*判斷對角線是否為可逆素數*/
{ printf("No.%d\n",++cc); p_array(); } /*輸出幻方矩陣*/
}
}
}
}
}
int num(int number) /*判斷是否可逆素數*/
{
int j;
if(!ok(number)) return 0;
for(j=0;number>0;number/=10) /*將素數變為反序數*/
j=j*10+number%10;
if(!ok(j)) return 0; /*判斷反序數是否為素數*/
return 1;
}
int ok(int number) /*判斷是否為素數*/
{
int i,j;
if(number%2==0) return 0;
j=sqrt((double)number)+1;
for(i=3;i<=j;i+=2)
if(number%i==0) return 0;
return 1;
}
void process(int i) /*將第i個整數分解為數字並存入數組*/
{
int j,num;
num=number[i][0];
for(j=4;j>=1;j--,num/=10)
number[i][j]=num%10;
}
void _num(int i) /*將array[i][0]指向的素數的各位數字復制到array[i]中*/
{
int j;
for(j=1;j<=4;j++)
array[i][j]=number[array[i][0]][j];
}
int comp_num(int n) /*判斷array中每列的前n位是否與可逆素數允許的前n位矛盾*/
{
static int ii; /*用內部靜態變數保存前一次查找到的元素下標*/
static int jj; /*ii:前一次查找前二位的下標,jj:前一次查找前三位的下標*/
int i,num,k,*p; /*p:指向對應的要使用的前一次下標ii或jj*/
int *pcount; /*pcount:指向要使用的臨時數組數量的計數器*/
switch(n){ /*根據n的值選擇對應的一組控制變數*/
case 2:pcount=&lcount[0];p=ⅈbreak;
case 3:pcount=&lcount[1];p=&jj;break;
default:return 0;
}
for(i=1;i<=4;i++) /*對四列分別進行處理*/
{
for(num=0,k=0;k<n;k++) /*計算前n位數字代表的數值*/
num=num*10+array[k][i];
if(num<=larray[n-2][*p]) /*與前一次最後查找到的元素進行比較*/
for(;*p>=0&&num<larray[n-2][*p];(*p)--);/*若前次查找到的元素大,則向前找*/
else
for(;p<pcount&&num>larray[n-2][*p];(*p)++); /*否則向後找*/
if(*p<0||*p>=*pcount)
{
*p=0; return 0;
}
if(num!=larray[n-2][*p])
return 0; /*前n位不是可逆素數允許的值則返回0*/
}
return 1;
}
int find1(int i) /*判斷列方向是否是可逆素數*/
{
int num,j;
for(num=0,j=0;j<4;j++)
num=num*10+array[j][i];
return find0(num);
}
int find2(void) /*判斷對角線方向是否是可逆素數*/
{
int num1,num2,i,j;
for(num1=0,j=0;j<4;j++)
num1=num1*10+array[j][j+1];
for(num2=0,j=0,i=4;j<4;j++,i--)
num2=num2*10+array[j][i];
if(find0(num1)) return(find0(num2));
else return 0;
}
int find0(int num) /*查找是否為滿足要求的可逆素數*/
{
static int j;
if(num<=number[j][0])for(;j>=0&&num<number[j][0];j--);
else for(;j<count&&num>number[j][0];j++);
if(j<0||j>=count){ j=0;return 0; }
if(num==number[j][0]) return 1;
else return 0;
}
void p_array(void) /*輸出矩陣*/
{
int i,j;
for(i=0;i<4;i++)
{
for(j=1;j<=4;j++) printf("%d ",array[i][j]);
printf("\n");
}
}
*問題的進一步討論
程序中大量技巧是用於盡早發現矛盾,減少循環次數,縮短運行時間。從實際效果看是相當不錯的。但目前的程序仍然可以進一步優化。
當第四行設定了前三行後,尚未設定的行就沒必要再使用窮舉的方法,因為列方向設定好的三位數字已經限制了最後一個數字可能的取值,在可逆數中找出前三位數字與設定好的三位數字相同的素數。這些素數就是在這一列前面已設定好的三位數字的限制條件下可能的取值。此時每一列上只有不超過四個可能的取值。找出全部各列可能的取值(可能的四位可逆素數),求出它們的交集。若交集為空,即沒有共同的可能取值,則列間數據相互矛盾否滿足則將交集中的數據填 入矩陣中就是題目的一個解。
演算法可再進一步優化。先窮舉一、二和四列的數據,然後用上面的演算法來確定第三行的值,這樣可進一步縮小窮舉的范圍,提高運行效率。
分析輸出的結果。可以看出本題的基本解只有17種,每個解可通過旋轉與反射獲得同構的其它7個解,可以進一步改進程序,只輸出17個基本解。
Ⅲ 誰知道用C語言怎麼寫求幻方的程序
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#define MAX_INDEX 100
void swap(int *a,int *b)
{
int t;
t=*a;
*a=*b;
*b=t;
}
/*快速排序演算法*/
void QuickSort(int a[], int l, int r)
{
int i=l; /*從左至右的游標*/
int j=r + 1; /*從右到左的游標*/
int pivot=a[l];
if (l >= r) return;
/*把左側>= pivot的元素與右側<= pivot 的元素進行交換*/
while (1)
{
do
{/*在左側尋找>= pivot 的元素*/
i = i + 1;
} while (a[i] < pivot);
do
{/*在右側尋找<= pivot 的元素*/
j = j - 1;
} while (a[j] > pivot);
if (i >= j) break; /*未發現交換對象*/
swap(&a[i],&a[j]);
}
/*設置p i v o t*/
a[l] = a[j];
a[j] = pivot;
QuickSort(a, l, j-1); /*對左段排序*/
QuickSort(a, j+1, r); /*對右段排序*/
}
void Huanf(int Array[][MAX_INDEX],int n)
{
int i,j;
int a,b,m;
int tempArray1[MAX_INDEX];
int tempArray2[MAX_INDEX];
a=n/2;
b=a+1;
m=n%4;
switch(m)
{
case 0:
case 2:
/*穿心對調*/
for(i=0;i<n;i++)
for(j=0;j<n/2;j++)
{
if(i<n/2)
{
if(i%2==1&&Array[i][j]%2==0)/*偶行換偶*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
else if(i%2==0&&Array[i][j]%2==1)/*奇行換奇*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
}
else
{
if(i%2==1&&Array[i][j]%2==1)/*偶行換奇*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
else if(i%2==0&&Array[i][j]%2==0)/*奇行換偶*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
}
}
/*End穿心對調*/
if(m==2)
{
for(i=0;i<n/2;i++)
{
if((i!=0)&&(i!=a-1)&&(i!=b-1)&&(i!=n-1))
{
swap(&Array[i][a-1],&Array[n-1-i][a-1]);
swap(&Array[b-1][i],&Array[b-1][n-1-i]);
}
}
swap(&Array[0][a-1],&Array[0][b-1]);
swap(&Array[a-1][0],&Array[b-1][0]);
swap(&Array[2][0],&Array[2][n-1]);
swap(&Array[0][2],&Array[n-1][2]);
}
break;
case 1:
case 3:
/*穿心對調*/
for(i=0;i<n;i++)
for(j=0;j<n/2;j++)
{
if(i<n/2)
{
if(i%2==1&&Array[i][j]%2==0) /*偶行換偶*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
else if(i%2==0&&Array[i][j]%2==0)/*奇行換奇*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
}
else if(i>n/2)
{
if(i%2==1&&Array[i][j]%2==0)/*偶行換偶*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
else if(i%2==0&&Array[i][j]%2==0)/*奇行換奇*/
{
swap(&Array[i][j],&Array[n-1-i][n-1-j]);
}
}
}
/*End穿心對調*/
/*重排米字*/
for(i=0;i<n;i++)
{
tempArray1[i]=Array[i][i];
tempArray2[i]=Array[a][i];
}
QuickSort(tempArray1,0,n-1);
QuickSort(tempArray2,0,n-1);
for(i=0;i<n;i++)
{
Array[i][i]=tempArray2[i];
Array[a][i]=tempArray1[i];
}
for(i=0;i<n;i++)
{
tempArray1[i]=Array[i][n-1-i];
tempArray2[i]=Array[i][a];
}
QuickSort(tempArray1,0,n-1);
QuickSort(tempArray2,0,n-1);
for(i=0;i<n;i++)
{
Array[i][n-1-i]=tempArray2[i];
Array[i][a]=tempArray1[i];
}
/*End重排米字*/
if(m==3)
{
for(i=0;i<n/2;i++)
{
if((i!=a-1)&&(i!=b-1)&&(i!=a+1))
{
swap(&Array[i][a-1],&Array[n-1-i][a-1]);
swap(&Array[a-1][i],&Array[a-1][n-1-i]);
}
}
swap(&Array[a-1][a-1],&Array[a+1][a+1]);
swap(&Array[a-1][b-1],&Array[a+1][b-1]);
}
break;
default:
break;
}
return;
}
void main()
{
int Ne[MAX_INDEX][MAX_INDEX];
int i,j,n;
while(1)
{
printf("Please Input N (0 quit): ");
scanf("%d",&n);
if(n==0)
break;
/*數組賦初值*/
for(i=0;i<n;i++)
for(j=0;j<n;j++)
Ne[i][j]=i*n+(j+1);
Huanf(Ne,n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf("%-4d",Ne[i][j]);
if(j==n-1)
printf("\n\n");
}
printf("\n\n");
getch();
}
}
Ⅳ 求素數幻方,這道題怎麼做啊(c語言)
4階的話,可以考慮直接遞歸搜索。我試了試有2992組解。
1 2 11 12
4 9 8 5
7 10 3 14
6 13 16 15
1 2 11 12
4 9 8 5
13 10 3 14
6 7 16 15
1 2 11 12
4 15 8 5
7 16 3 14
6 13 10 9
1 2 11 12
4 15 8 5
13 16 3 14
6 7 10 9
1 2 11 12
10 3 8 5
7 16 15 14
6 13 4 9
1 2 11 12
10 3 8 5
13 16 15 14
6 7 4 9
1 2 11 12
10 9 8 5
7 4 3 14
6 13 16 15
1 2 11 12
10 9 8 5
7 4 15 14
6 13 16 3
1 2 11 12
10 9 8 5
13 4 3 14
6 7 16 15
1 2 11 12
10 9 8 5
13 4 15 14
6 7 16 3
…………
#include <stdio.h>
#include <math.h>
#include <windows.h>
#define MAX_NUM 30
#define _PRINT_ 0
unsigned long Result[MAX_NUM * MAX_NUM], ResultNum, Used[MAX_NUM * MAX_NUM]={0};
bool PrimeTable[MAX_NUM * MAX_NUM * 2]={ false };
unsigned long N, QN;
void CreatePrimeTable(void)
{
PrimeTable[0]=false;
PrimeTable[1]=false;
PrimeTable[2]=true;
PrimeTable[3]=true;
for(unsigned long j=5; j <= MAX_NUM * MAX_NUM * 2; j+=2)
{
PrimeTable[j]=true;
for(unsigned long i=3; i <= sqrt((double)j); i+=2)
{
if(j % i == 0)
{
PrimeTable[j]=false;
break;
}
}
}
}
inline bool IsPrime(unsigned long n)
{
return PrimeTable[n];
}
bool CheckIt(unsigned long Deep)
{
if(Deep == 0)
{
return true;
}
else if(Deep < N)
{
return IsPrime(Result[Deep] + Result[Deep - 1]);
}
else if(Deep % N == 0)
{
return IsPrime(Result[Deep] + Result[Deep - N]);
}
else
{
return(IsPrime(Result[Deep] + Result[Deep - 1]) && IsPrime(Result[Deep] + Result[Deep - N]));
}
}
void go(unsigned long Deep)
{
if(Deep == QN)
{
ResultNum++;
#if (_PRINT_)
printf("Find it! No.%lu\n", ResultNum);
for(unsigned long i=0; i < QN; i++)
{
printf("%lu\t", Result[i]);
if(i % N == N - 1)
{
printf("\n");
}
}
#else
printf("\rFind:%lu", ResultNum);
#endif
}
else
{
for(unsigned long i=1; i <= QN; ++i)
{
if(!Used[i])
{
Result[Deep]=i;
if(CheckIt(Deep))
{
Used[i]=1;
go(Deep + 1);
Used[i]=0;
}
}
}
}
}
int main()
{
DWORD tim;
ResultNum=0;
printf("Input N:");
scanf("%lu", &N);
QN=N * N;
tim=GetTickCount();
CreatePrimeTable();
go(0);
printf("\n\nN=%lu\n", N);
printf("Total=%lu\n", ResultNum);
printf("Time=%lu\n", GetTickCount() - tim);
return 0;
}
關於補充問題:
相鄰 不包含斜方向的吧?相鄰不就是上下、左右……包含斜線的話,再增加一種情況就可以了。不過用的時間會多點
Ⅳ 魔方陣的C語言
代碼一:
#include <stdio.h>
#define N 16 //這里可以修改N的值,並且N只能為偶數
int main()
{
int a[N][N]={0},i,j,k,p,m,n;
p=1;
while(p==1)
{
printf(Enter n(1~%d): ,N-1);/*可以輸入小於等於N-1的奇數*/
scanf(%d,&n);
if((n!=0)&&(n<N)&&(n%2!=0)) p=0;
}
i=n+1;
j=n/2+1; /*建立魔方陣*/
a[1][j]=1;
for(k=2;k<=n*n;k++)
{
i=i-1;
j=j+1;
if((i<1)&&(j>n))
{
i=i+2;j=j-1;
}
else
{
if(i<1) i=n;
if(j>n) j=1;
}
if(a[i][j]==0) a[i][j]=k;
else
{
i=i+2;
j=j-1;
a[i][j]=k;
}
}
for(i=1;i<=n;i++)/*輸出魔方陣*/
{
for(j=1;j<=n;j++)
printf(%4d,a[i][j]);
printf(
);
}
}
代碼二:(相對於代碼一條理更清晰,更簡單、更容易理解)
將1~n的平方這幾個數構成一個n階魔方陣。
演算法:
依以下法則,你可以很快的寫出奇數階幻方!當然,這種寫法只是其中一個答案,而不是唯一答案。
1)將1填入第一行中間;
2)將每個數填在前一個數的右上方。
3)若該位置超出最上行,則改填在最下行的對應位置;
4)若該位置超出最右列,則該填在最左列的對應行位置;
5)若某元素填在第一行最右列,下一個數填在該數同列的下一行;
6)若某數已填好,但其右上角已填了其他數據,則下一個數填在該數同列的下一行位置。
#include<stdio.h>
void main()
{
int a[15][15]={0},i,j,m,n,temp,M;
printf(請輸入一個3~15的奇數:
);
scanf(%d,&M);
i=0;
j=M/2;
a[i][j]=1;
for(temp=2;temp<=M*M;temp++)
{
m=i;
n=j;
i--;
j++;
if(i<0)
i=M-1;
if(j>M-1)
j=0;
if(a[i][j]!=0)
{
i=m+1,j=n;
a[i][j]=temp;
continue;
}
a[i][j]=temp;
}
printf(%d×%d魔方陣:
,M,M);
for(i=0;i<M;i++)
{
for(j=0;j<M;j++)
printf(%4d,a[i][j]);
printf(
);
}
}
//(求4的倍數階幻方)
void main()
{
int i,j,x,y,n,t,k=1;
int a[100][100];
printf(請輸入魔方陣的階數n
);
scanf(%d,&n);
printf(輸出為:
);
if(n%4==0)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
a[i][j]=k;
k++;
}
x=n-1;
for(j=0;j<n/2;j++,x--)
{
for(i=0;i<n;i++)
if(i%4!=j%4&&(i+j)%4!=3)
{
t=a[i][j];
a[i][j]=a[i][x];
a[i][x]=t;
}
}
x=n-1;
for(i=0;i<n/2;i++,x--)
{
for(j=0;j<n;j++)
if(i%4!=j%4&&(i+j)%4!=3)
{
t=a[i][j];
a[i][j]=a[x][j];
a[x][j]=t;
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf(%-4d,a[i][j]);
printf(
);
}
}
else printf(輸入錯誤
);
system(pause...);
}
Ⅵ 4階幻方的解法,詳細的
解法1.(對稱交換法)
1.求幻和
(12……16)÷4=34
2.
⑴將1~16按自然順序排成四行四列;
⑵因為每條對角線上四個數之和恰為幻和,保持不動.
⑶將一四行交換、二三行交換,但是對角線上八個數不動。
⑷將一滑橘四列交換、二三列交換,但是對角線上八個數不動。
(1)
1 2 3 4
5 6 7 8
9 101112
13141516
(2)
114 15 4
9 6 7 12
5 10 118
13 2 316
(3)
1 15144
12 6 79
8 10115
13 3216
解法2.(田格圖陣法)
1.將1~16平均分為4組,每組4個數的和均為幻和34.(多種分法)如:
112714=211813=310516=49615=34.
2.分別填入4個田字格,兩行之和分別為13與21.
3.將4個田格合並,再適當轉動各田格,得到滿足要求的段讓頃幻方.
解法3:(推理法)
常用,雖然速度不是很快。其實就是在1~16這16個數找到四個數相加為34的數填在四階幻方的正中間,然後按照一定的推理方法填入其它空格內。
(方法挺笨重,但挺實用的握陸)
解法4:(方程法)
四階幻方,可以有設置5個未知數到裡面,只要代進其中的數,可以推出其它的數,具體設置位置,可以看下附圖(應該上傳的得了)
解法5:程序法
計算機的運算速度非常快,所以採用程序計算可以很快得到,至於什麼樣的程序,可以根據很多不同的演算法得到每一種方法。舉個例子,用程序法解三階幻方,可以用「樓梯法」的精髓思想,也可以用「楊輝法」的精髓思想。
Ⅶ 四階幻方的解法
四階(加法)幻方很容易制。
第一步:選數。選取十六個數,把所選的十羨帶六個數按一定順序排列成四行四階的方陣,如果每一行、每一列的數都成等差數列,那麼用這十六個數就能製成四階幻方。下面以1、2、3、4……15、16這十六個數為例說明四階幻方的製法。
第二步:把這十六個數按順序填入四行四列的方陣。
上面的三步做完,四階幻方就完成了。
幻方製作完成後,對稱地交換兩行數或者兩列數(如交換第一行與第四行、第二行與第三行),幻方仍然成立。
Ⅷ 請教4階幻方的求解方法
四階幻方的方法很多種,其中最簡單的方法:【順序填數,以中心點對稱互換數字】。
互換數字的方法有兩種:
1、互換對角線上的數;
2、互換非對角線上的數。
(8)求解四階幻方的C語言擴展閱讀
起源記載
在一個由若干個排列整齊的數組成的正方形中,圖中任意一橫行、一縱行及對角線的幾個數之和都相等,具有這種性質的圖表,稱為「幻方」。中國古代稱為「河圖」、「洛書」,又叫「縱橫圖」。
九宮洛書蘊含奇門遁甲的布陣之道。九宮之搭陪數源於《易經》。幻方也稱縱橫圖、魔方、魔陣,它是科學的結晶與吉祥的象徵,發源於中國古代的洛書——九宮圖。
公元前一世紀,西漢宣帝時的博士戴德在他的政治禮儀著作《大戴禮·明堂篇》中就有「二、九、四、七、五、三、六、一、八」的洛書九宮數記載。洛書被世界公認為組合數學的鼻祖,它是中華民族對人類的偉大貢獻之一。
洛書以其高度抽象的內涵,對中國古代政治倫理、數學、天文氣象、哲學、醫學、宗教等都產生了重要影響。
在遠古傳說中,於治國安邦上也具有積極的寓意!包括洛書在內的幻方自古以來在亞、歐、美洲不少國家都被作為驅邪避凶的吉祥物,這種古代地域廣泛的圖騰應該說是極其少見的。1975年上海人民出版社出版的自然辯證法叢書《自然科學大事年表》,
《大戴禮》記載,中國古代有象徵吉祥的河圖洛書縱橫圖,即為九宮算,被認為是現代『組合數學』最古老的發現。」
2500年前,孔子在他研究《易經》的著作《系詞上傳》中記載了:「河出圖,洛出書,聖人則之。」最早將數字與洛書相連的記載是2300年前的《莊子·天運》,它認為:「天有六極五常,帝王順之則治,逆之則凶。九洛之事,治成德備,監照下土,天下戴之,此謂上皇。」
明代數學家程大位在《演算法統宗》中也曾發出「數何肇?其肇自圖、書乎?伏羲得之以畫卦,大禹得之以序疇,列聖得之以開物」的感嘆,大意是說,數起源於遠古時代黃河出現的河圖與洛水出現的洛書知鄭蠢,伏羲依靠河圖畫出八卦,大禹按照洛書劃分九州,並制定治理天下的九類大法。
大禹從洛書中數的相互制約,均衡統一得到啟發而制定國家的法律體系,使得天下一統,歸於大治,這是借鑒思維的開端。這種活化思維的方式已成為科學靈感的來源之一。從洛書發端的幻方在數千年後更加生機盎然,被稱為具有永恆魅力的數學問題。
十三世紀,中國南宋數學家楊輝在世界上首先開展了對幻方的系統研究,歐洲十四世紀也開叢早始了這方面的工作。著名數學家費爾瑪、歐拉都進行過幻方研究,
如今,幻方仍然是組合數學的研究課題之一,經過一代代數學家與數學愛好者的共同努力,幻方與它的變體所蘊含的各種神奇的科學性質正逐步得到揭示。它已在組合分析、實驗設計、圖論、數論、群、對策論、紡織、工藝美術、程序設計、人工智慧等領域得到廣泛應用。
1977年,4階幻方還作為人類的特殊語言被美國旅行者1號、2號飛船攜入太空,向廣袤的宇宙中可能存在的外星人傳達人類的文明信息與美好祝願。
Ⅸ 求C語言編寫四階幻方程序!用數組!
#include<銀森stdio.h>
void main()
{
int i,j,k;
int a[4][4];
for(i = 0,k = 1; i < 4; i++)
for(int j = 0; j < 4; j++)
{
if((i == j) || (i + j == 3))
a[i][j] = 17 - k;
else
a[i][j] = k;
k++;
}
for(i = 0; i <寬亮 4; i++)
{
for(j = 0; j < 4; j++)
printf("%-4d",a[i][j]);
printf("\n");
}
}
你最好去看一下鋒巧畝幻方的規律!