前言:
最近在看組合數學,記錄一些書中相關的知識點。
正文:
考慮一個普通的國際象棋棋盤,它被分成8*8(8行8列)的64個正方形。設有形狀一樣的多米諾骨牌,每張牌恰好覆蓋棋盤上相鄰的兩個方格(即1*2的骨牌)。那麼能否把32個這樣的12骨牌放到棋盤上,使得任何兩張牌均不重疊,每張多米諾骨牌覆蓋兩個方格,並且棋盤上所有的方格都被覆蓋住?我們把這樣一種排列稱為被多米諾骨牌的完美覆蓋。這是一個簡單的排列問題,人們能夠很快構造許多不同的完美覆蓋。但是計算不同的完美覆蓋的總數就不是一件容易的事了,不過,這還是有可能做到的。這個數由 M.E.Fischer在其一篇名為Statistical Mechanics of Dimers on a Plane Lattice的論文中計算出了不同的完美覆蓋總數為: 12988816 = 24 * (901)2 。而後Fischer得出了更一般的公式用來求解12骨牌覆蓋m*n(m,n至少一個為偶數)方格的公式, 。其實這就是分子生物學著名的二聚物問題。
分析完上面的問題,大家自然會有一個問題,對於一般的1*b的方格來覆蓋m*n的棋盤,完美覆蓋數又是多少呢?這裡,我們稱1*b的方格為b-牌(b-omino)。一個已知的事實是,如果一個m*n的棋盤擁有b牌的完美覆蓋,那麼b是m的一個因子或者b是n的一個因子。本文將給出0<b<5,用來覆蓋m*n棋盤的方法數(我們令n不大於m):
1)b=1 的情況
顯然,覆蓋方法數只有1種
2)b=2的情況
前面提到了Fischer的三角公式,但是有個問題,如果結果很大的時候,需要給出取模解的時候,用公式就顯得力不從心了。
i)而我們發現當n=2的時候,結果數剛好是Fibonacci數列。對於m較大可以用矩陣冪演算法解決。
ii)n=3的時候可以推倒出遞推式
以及邊界條件
其中\(a_m\)代表在左上角將第一塊骨牌橫著放的總方案數,\(b_m\)代表在左上角豎著放第一塊骨牌的方案數。
不難得出\(a_m\)的表示式,繼而使用矩陣冪求出大資料求模的解。周源在WC08的講稿中給出了\(a_m\)和\(b_m\)的生成函式:
iii) n>3的情況。其實我們注意到b=2,應該能夠考慮到二進位制,繼而考慮到狀態壓縮動態規劃。首先dfs出相鄰兩行的狀態轉移方式\(S_{from}->S_{to}\),繼而用動態規劃轉移得到每行的方案數Hs。不難看出時間複雜度為O(m*2n)。菜魚同學利用特徵方程計算了每行的方案數Hs=,由於第二項較小可以忽略,因此Hs約等於0.85*2.414n,即2n<Hs<3n。因此一個更加精確的時間複雜度為O(m*0.85*2.414n), 不難看出這裡n的範圍比較小,一般小於12。
3) b=3的情況或者b=4的情況
均可以利用上述推倒遞推關係的方法求解。
最後推薦幾個相關的資料供讀者參考:
馮躍峰. 棋盤上的組合數學.[M]. 上海:上海教育出版社,1998.
沈曉斌 棋盤的1*3骨牌骨牌覆蓋的技術.[J]. 泉州師專學報, 1997,(2)
沈曉斌等1*4格牌覆蓋棋盤的計數.[J]. 泉州師專學報, 2000,(2)