拉丁方
-
問題描述
拉丁方又稱拉丁圖,是一種 n × n 的方陣,在這種 n × n 的方陣裏,恰有 n 種不同的元素,每一種不同的元素在同一行或同一列裏只出現一次。 -
思路解析
每次對矩陣中的一位賦值,就進行一次條件檢查,利用窮舉的辦法得出所有矩陣。 -
python語言實現如下
def matrix_formation(x, y, n): # 生成所有符合的矩陣並計數
global counting
global num
global matrix
if counting == (n*n):
matrix_print(n) # 若內容已生成,輸出矩陣並計數
num += 1
else:
for i in range(1, n+1): # 產生矩陣內容
matrix[x][y] = i
counting += 1
if martix_inspection(x, y):
x1 = x
y1 = (y + 1) % n
if y == (n - 1):
x1 = x + 1
matrix_formation(x1, y1, n)
counting -= 1 # 遞歸完成後重新生成矩陣
def martix_inspection(x, y): # 檢查元素是否在同行同列出現
global matrix
ins_num = matrix[x][y]
for i in range(y):
if ins_num == matrix[x][i]:
return 0
for i in range(x):
if ins_num == matrix[i][y]:
return 0
return 1 # 符合條件返回1
def matrix_print(n): # 輸出矩陣
for i in range(n):
for j in range(n):
print(matrix[i][j], end=' ')
print('')
print('')
a = int(input("請輸入方針階數:"))
print('')
print("符合條件方陣如下:")
print('')
global counting, num, matrix # 定義全局變量
counting = 0
num = 0
matrix = [[0] * a for _ in range(a)]
matrix_formation(0, 0, a)
print("可得:%d階方陣有%d個拉丁圖" % (a, num))
放球問題
-
問題描述
放球問題是一類經典問題,即把n個小球放到k個盒中,小球是否有區分,盒子是否有區分,盒子是否爲空,n和k的大小比較,這些情況可以組合成不同的場景,有着不同的解決方法。該類問題在網上有着專門的百科分析,直接搜索“放球問題”即可得到各種情況的解析。 -
思路解析
本次針對的場景是:小球有區分,盒子有區分,盒子不能爲空。首先假設盒子不可區分,計算可能方案可採用第二類斯特林數公式進行計算,即S(n,k)=S(n-1,k-1)+k*S(n-1,k), 再計算可區分的盒子排列,即爲k的階乘,因此總的方案數num=S(n,k)*k!。 -
python語言實現如下
from numba import jit
@jit(nopython=True) # 加快計算速度
def stirling(n, k): # 第二種斯特林數公式,即S(n,k)=S(n-1,k-1)+k*S(n-1,k)
if k > n or k == 0: # 若盒數大於球數,一定有盒子爲空;若盒數爲0,不滿足條件
return 0
elif k == n: # 若盒數等於球數,就只有一種辦法
return 1
elif k == 1: # 若盒數爲1,也只有一種辦法
return 1
return stirling(n-1, k-1) + stirling(n-1, k) * k
n = int(input("請輸入小球數量:"))
k = int(input("請輸入盒子數量:"))
num = 1
for i in range(1, k+1): # 計算k的階乘
num = num * i
num = num * stirling(n, k) # 假設盒子是無區別的,即有S(n,k)種方案,再對盒子排列,有k的階乘種
print("%e" % num)