自編的乙個魔方(數陣)演算法,效率很高

2021-05-24 04:55:16 字數 3221 閱讀 6943

n*n數陣就是n*n魔方,要求每行每列及對角線之和都相等。下面是大學時用tc寫的乙個演算法,效率很高,找到所有4階需要16秒,剛才增加三行**消除對稱的魔方,只需2秒即可找到所有的832種可能(不輸出結果,只計數)。暫時還不知道標準答案,可能有遺漏或重複。

求解n階魔方,即將1、2、3…n*n放入n*n的矩陣中,使得每行每列及兩條對角線上的n個數的和都相等(等於sum=(n*n)*(1+n*n)/(2*n))。

主要演算法及思想:

首先得到所有的n個數的和為sum的組合情況,放在陣列all[m][n]中,其中每一組中的n個數都是從小到大排列,m為所有的組的個數。num[n*n]中存放了包含數字1、2…n*n的組的個數。index[m*n]中存放了包含1、2…n*n的組的序號(以此序號可在all中找到對應的n個數),其中單元1-num[1]中存放的是包含數字1的所有組的序號,單元num[1]+1-num[2]中存放了包含數字2的所有組的序號……。為方便得到包含任乙個數字n的所有的組的序號,構造一存放查詢偏移量的陣列offset[n*n],其中存放的是在index陣列中查詢包含任一數字的組的序號時的起始偏移量,如:要找包含數字n的所有組,可以從index陣列中offset[n]-offset[n]+num[n]單元得到組的序號,以此序號再到陣列all中得到組中的n個數字。

由於每乙個組中的數字都是從小到大排列的,要得到同樣n個數字的其他排列方式,可以通過函式rotat得到(n個數共有n!種排列方式)。

matrix[n][n]中存放的是n*n階矩陣的每乙個元素。得到魔方的步驟如下:

1。取一組的n個數字,按一種排列方式,放入矩陣的第一行。

2。取乙個包含第一行第一列中數字的組,按一種排列方式,放入矩陣的第一列。

3。取乙個包含第一行第二列中數字的組,按一種排列方式,放入矩陣的第二列:

每一列列中的每乙個數字(除第一行的),都要與同一行的已放置的數字可以在同乙個組中,如果是兩條對角線上的數字,還要考慮與已放好的對角線上的數字能存在於同乙個組中。如果不能滿足這個條件,則更換這一列的n的數字的排列方式,如果所有的排列方式都不行,則另選一組放入此列中,若所有的組的任一種排列方式都不能放入此列,則將前一列的n個數字換乙個排列方式,以此類推。

通過函式checkg(int group,int col)判斷第group組能否放入第col列中;通過函式checkr(int col)判斷將某一組按某一方式放入第col列後,已有的所有元素能否同時存在。

從以上的分析知,必須記錄第一行和每一列中放置的組的序號和排列方式,以便更改。這些資訊存放在陣列states[n+1][3]中,其中第一維表示第一行和n列,第二維的3個單元分別存放:組的序號,排列方式,在包含某一數字的所有組中的位置。

以下為n=3,m=8(sum=15)時的乙個例項分析:

all[8][3]:

0:1 5 9(該組的序號為0,用0表示該組)

1:1 6 8(該組的序號為1,用1表示該組)

2:2 4 9

3:2 5 8

4:2 6 7

5:3 4 8

6:3 5 7

7:4 5 6

三個數字的和為15的組合只有以上8中。

所有組中包含數字1的組有(用組的序號表示):0 1;包含數字2的組有:2 3 4;包含數字3的組有:5 6;……

num[9]:   2     3     2     3       4       3     2     3     2

index[24]:

(0 1)(2 3 4)(5 6)(2 5 7)(0 3 6 7)(1 4 7)(4 6)(1 3 5)(0 2)

(0 1)為包含數字1的組;(2 3 4)為包含數字2的組;(5 6)為包含數字3的組;……

offset[9]:0   2      5    7      10       14     17   19     22

如要找包含數字5的組,可在index中的10-10+4單元中找到組的序號0、3、6、7

(10=offset[5-1];4=num[5-1])

尋找魔方的步驟:

1。將第一組按第一種排列方式放入第一行,states[0][0]=states[0][1]=0;

1 5 9

0 0 0

0 0 0 (0表示還未放入數字)

2。考慮放入第一列:

找到包含數字1的所有組中的第乙個組(0:1 5 9),即states[1][2]=0;states[1][0]=0;

由於此組已經用於放在第一行中,不符合條件。

找到包含數字1的所有組中的第二個組(1:1 6 8),即states[1][2]++;states[1][0]=1;

此組符合條件,按第一種排列方式將6 8放入第一列states[1][1]=0;

1 5 9

6 0 0

8 0 0

由於副對角線上的8和9不能同時出現在乙個組中,不符合條件

按第二種排列方式將6 8放入第一列states[1][1]++;

1 5 9

8 0 0

6 0 0

副對角線上的6 9也不能同時出現在一組,不符合條件

由於沒有其他的排列方式,只能另選一組

包含數字1的組都不能滿足條件,故考慮更換第一行

3。將第一行中的n個數換一種排列方式:states[0][1]++;

1 9 5

0 0 0

0 0 0

4。考慮放入第一列:

states[1][2]=0;states[1][0]=0;此組已放入第一行

states[1][2]++;states[1][0]=1;states[1][1]=0;

1 9 5

6 0 0

8 0 0

5。考慮放入第二列:

找到包含數字9的所有組中的第乙個組(0:1 5 9),即states[2][2]=0;states[2][0]=0;

由於此組已用於第一行,不符合條件。

找到包含數字9的所有組中的第二個組(2:2 4 9),即states[2][2]++;states[2][0]=2;

按第一種排列方式states[2][1]=0;

1 9 5

6 2 0

8 4 0

由於主對角線上的1 2不能同時存在於一組中,不符合條件

states[2][1]++;

1 9 5

6 4 0

8 2 0

兩條對角線均不符合條件

包含數字9的組均不符合條件,考慮更換第一列

……最終找到乙個魔方:

6 1 8

7 5 3

2 9 4

乙個魔方矩陣的個人演算法

這樣乙個魔方矩陣 按以下示例方陣格式,生成乙個由自然數1至n 2組成的n階方陣。1 3 4 10 11 2 5 9 12 19 6 8 13 18 20 7 14 17 21 24 15 16 22 23 25 注 n不僅限於5。我的 include using namespace std defi...

線上診斷乙個load很高的問題

從監控系統中發現某集群的load很高,分析到最後發現是大量的disk io引起的。於是優化了上傳的元件不寫臨時檔案 發現io還是很高。再測試,竟然是apache的預設filter被改變後觸發了mod proxy的寫臨時檔案的條件,由於apache是寫死在 中的無法配置,於是將filter 重新註冊為...

LvClass 的乙個效率

前幾天,聽到了乙個客戶的抱怨 他編寫了乙個labview程式,每次開啟主程式就要花費幾分鐘的時間,這有點令他忍無可忍。我沒有見過他的源程式,不過據幫他檢查過程式的同事講,他的問題很可能是使用了大量的lvclass造成的。在他的專案中,包含有上百個類 lvclass 我以前也聽說過lvclass在效率...