拉丁方
-
问题描述
拉丁方又称拉丁图,是一种 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)