编程练习(四)(拉丁方和放球问题)

拉丁方

  • 问题描述
    拉丁方又称拉丁图,是一种 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)
发布了13 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/CSDNTianJi/article/details/102244749
今日推荐