魔方陣:3階、4階、8階演算法與實現
魔方陣:一個N階魔方陣即N行N列的陣列,其每一行的和==每一列的和==對角線的和。
例如一個3階魔方陣:
8 1 6
3 5 7
4 9 2
一:3階魔方陣
這裡我們用兩種方法實現:
方法一:遍歷三階陣列的所有條件,將符合條件的(行的和==列的和==對角線和)挑出來。這種方法可以打印出多種情況。
方法二:
1.將1放在第一行的中間
2.後面的數字放在當前數字的的上一行後一列
3.如果當前位置有資料,就放在前一個數字的下一行同列
方法一程式碼:
bool TiaoJian_1(int arr[3][3])//魔方陣的條件:9個數字互不相等
{
if(arr[0][0] != arr[1][0] && arr[0][0] != arr[1][2] && arr[0][1]!= arr[1][1] &&
arr[0][0] != arr[0][1] && arr[0][1] != arr[0][2] && arr[0][2] != arr[1][0]&&
arr[1][0] != arr[1][1] && arr[1][1] != arr[1][2] && arr[1][2] != arr[2][0]&&
arr[2][0] != arr[2][1] && arr[2][1] != arr[2][2] && arr[1][0]!= arr[2][0])
{
return true;
}
else
{
return false;
}
}
bool Tiaojian_2(int h[3],int l[3],int dj[2])
{
if(h[0]==h[1] && h[1]==h[2] && h[2]==l[0] &&
l[0]==l[1] && l[1]==l[2] && l[2]==dj[0] &&dj[0]==dj[1])
{
return true;
}
else
{
return false;
}
}
int MagicCube_3()
{
int arr[3][3];
int h[3];
int l[3];
int dj[2];
int n = 10;
for(int i1 = 1;i1<n;i1++)//給3*3個元素分別賦值1~10,共9^9種情況;一個for迴圈一個元素,共9個
{
arr[0][0] = i1;
for(int i2 = 1;i2<n;i2++)
{
arr[0][1] = i2;
for(int i3 = 1;i3<n;i3++)
{
arr[0][2] = i3;
for(int j1 = 1;j1<n;j1++)
{
arr[1][0] = j1;
for(int j2 = 1;j2<n;j2++)
{
arr[1][1] = j2;
for(int j3 = 1;j3<n;j3++)
{
arr[1][2] = j3;
for(int k1 = 1;k1<n;k1++)
{
arr[2][0] = k1;
for(int k2 = 1;k2<n;k2++)
{
arr[2][1] = k2;
for(int k3 = 1;k3<n;k3++)
{
arr[2][2] = k3;
if(TiaoJian_1( arr ))
{
for(int i = 0;i <= 3;i++)//h[0] h[1] h[2]
{
h[i] = arr[i][0]+arr[i][1]+arr[i][2];
l[i] = arr[0][i]+arr[1][i]+arr[2][i];
}
dj[0] = arr[0][0]+arr[1][1]+arr[2][2];
dj[1] = arr[0][2]+arr[1][1]+arr[2][0];
if(Tiaojian_2(h,l,dj))
{
for(int i = 0;i < 3;i++)
{
for(int j = 0;j < 3;j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
printf("\n\n");
}
}
}
}
}
}
}
}
}
}
}
return 0;
}
這個方法的時間複雜度太大,程式碼也沒有優化,把所有情況列印完畢計算機要執行5分鐘左右。第一次體會到跑程式碼的快感。
方法二程式碼如下:
void Magic_teacher_3()
{
#define ROW 3
#define COL 3
int arr[ROW][COL] = {0};//將arr全部元素置零
int row = 0;
int col = COL/2;
arr[row][col] = 1;//將1放在第一行的中間
for(int i = 2;i <= ROW*COL;i++)//2.後面的數字放在當前數字的的上一行後一列
//3.如果當前位置有資料,就放在前一個數字的下一行同列
{
row--;//上一行
if(row < 0)//如果行為負數,把行置為最後一行
{
row += ROW;
}
col++;//下一列
if(col > COL-1)//如果列大於最高列,把col置為第一列
{
col = COL - col;
}
if(arr[row][col] != 0)//如果當前位置有資料,放到前一數字的下一行同列
{
row = (row + 2) % ROW;
col = (col-1+COL) %COL;
}
arr[row][col] = i;
}
for(int i= 0;i < ROW;i++)//列印魔方陣
{
for(int j = 0;j < COL;j++)
{
printf("%-3d",arr[i][j]);
}
printf("\n");
}
}
二:4階魔方陣(同8階演算法類似)
這裡也用兩種方法實現。
方法一:
void MagicCube_4()//4階魔方陣
{
#define N 4
int arr[N ][N ];
int m = 1;
for(int i = 0;i < N;i++)
{
for(int j = 0;j < 4;j++)
{
arr[i][j] = m++;
}
}
int Firstnum = arr[N-1][N-1];
//主對角線清零
for(int i= 0;i <N;i++)
{
for( int j = 0 ;j<N;j++)
{
if(i == j)
{
arr[i][j] = 0;
}
}
}
//副對角線清零
for(int i = 0;i < N;i++)
{
for(int j = 0;j < N;j++)
{
if((i+j) == 3)
{
arr[i][j] = 0;
}
}
}
//對角線填數字 firstnum = 16;第一個數字為16
for(int i = 0;i<N;i++)
{
for(int j = 0;j<N;j++)
{
if(arr[i][j] == 0)
{
arr[i][j] = Firstnum --;
}
else
{
Firstnum--;
}
}
}
//列印結果
for(int i = 0;i< N;i++)
{
for(int j = 0;j<N;j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
方法二:
這裡的從右上至左下應該為: ((i+j)%4)!=3
程式碼如下:
void Magic_8()//8階或者4階魔方陣
{
#define ROW 8
int arr[ROW][ROW];
int tmp = 1;
int tmp2 = ROW*ROW;
for(int i=0;i<ROW;i++)
{
for(int j=0;j<ROW;j++)
{
if((i%4!=j%4) && ((i+j)%4!=3))
{
arr[i][j] = tmp;
}
else
{
arr[i][j] = tmp2;
}
tmp++;
tmp2--;
}
}
for(int i=0;i<ROW;i++)
{
for(int j=0;j<ROW;j++)
{
printf("%-4d",arr[i][j]);
}
printf("\n");
}
/*if(!Check(arr,ROW))//準備寫一個檢查函式,檢查每行每列對角線的和是否相等。(待更新)
{
printf("不是魔方陣\n");
}*/
}