3枚6面骰子点数和为3的排列计数Python函数编写问题
骰子求和计数问题解答
3枚6面骰子总和为3的情况数
投掷3枚标准6面骰子时,单枚骰子最小点数为1,总和的最小值为1+1+1=3,因此总和为3的排列仅1种,即三枚骰子点数均为1,不存在其他可能——只要任意一枚骰子点数大于1,剩余两枚最小取1时总和都会超过3。
现有代码思路的问题
你当前写的嵌套循环思路存在几个明显错误,无法正确求解这类问题:
- 循环层数固定为2层,只能适配2枚骰子的场景,无法灵活支持任意数量的骰子(比如本次问题的3枚骰子)
range参数设置错误:6面骰子点数范围是1~6,range(numberof_sides)生成的是0到numberof_sides-1的整数,不符合骰子点数规则;第二层循环用range(sum_of_dice)作为遍历范围也不合理,单枚骰子点数上限是面数,不是目标总和- 缺少核心的计数、取值约束逻辑,没有对剩余骰子的点数范围做判断,就算补全现有变量也无法得到正确结果
通用求解函数实现
这类问题属于典型的骰子求和计数问题,有两种常用实现方案:
方案1:动态规划(适合骰子数量多的场景,计算效率高)
核心思路是用状态数组记录n个骰子掷出对应总和的情况数,递推计算结果,避免无意义的枚举:
def count_dice_permutations(dice_count: int, side_count: int, target_sum: int) -> int: # 先判断目标总和是否在合法范围内,不在直接返回0 min_possible = dice_count * 1 max_possible = dice_count * side_count if target_sum < min_possible or target_sum > max_possible: return 0 # 初始化dp数组,dp[i][j]表示i个骰子掷出总和j的排列数 dp = [[0] * (max_possible + 1) for _ in range(dice_count + 1)] dp[0][0] = 1 for i in range(1, dice_count + 1): # i个骰子的总和范围是i ~ i*side_count for j in range(i, i * side_count + 1): # 枚举第i个骰子的可能点数 for point in range(1, side_count + 1): if j - point >= 0: dp[i][j] += dp[i-1][j - point] return dp[dice_count][target_sum]
调用count_dice_permutations(3, 6, 3)会返回1,和手动计算的结果一致。
方案2:直接枚举(适合骰子数量少的场景,可直接输出所有排列)
如果需要拿到所有符合要求的点数排列,而不只是计数,可以直接生成所有投掷结果再筛选:
from itertools import product def list_dice_permutations(dice_count: int, side_count: int, target_sum: int) -> list: # 生成所有骰子的点数组合,单枚骰子点数范围1~side_count all_roll_results = product(range(1, side_count + 1), repeat=dice_count) # 筛选出总和等于目标值的组合 return [roll for roll in all_roll_results if sum(roll) == target_sum]
调用list_dice_permutations(3,6,3)会返回[(1,1,1)],符合预期。
内容的提问来源于stack exchange,提问作者Barrett_Davis
相关产品推荐
相关产品推荐

