目录
题目
小明有n个可选运动,每个运动有对应卡路里,想选出其中k个运动且卡路里和为t。k,t,n都是给定的。求出可行解数量
输入描述
第一行输入n t k
第二行输入 每个运动的卡路里 按照空格进行分割
备注
0<n<10
t>0,0<k<=n
每个运动量的卡路里>0
输出描述
求出可行解数量示例1:
输入
4 3 2
1 1 2 3输出
2
说明
可行解为2,选取{0,2},{1,2}两种方式。
思路
1. 问题分析
1.1 题目理解
输入内容的详细解释:
- 第一行包含三个整数:n(运动总数)、t(目标卡路里和)、k(需要选择的运动数量)
- 第二行包含n个整数,表示每个运动的卡路里值,以空格分隔
输出要求的具体说明:
- 输出一个整数,表示满足条件的组合数量
- 条件:从n个运动中选择k个,使得这k个运动的卡路里和等于t
约束条件的整理:
- 0 < n < 10(运动总数小于10)
- t > 0(目标卡路里和为正数)
- 0 < k <= n(选择的运动数量大于0且不超过总运动数)
- 每个运动的卡路里值均为正数
1.2 问题建模
将问题转化为具体的数据结构:
- 输入的运动卡路里可以用数组表示
- 本质是一个组合问题,需要从n个数中选择k个数,使其和为t
确定需要使用的算法类型:
- 这是一个组合计数问题
- 可以使用回溯法(DFS)或动态规划来解决
分析问题的数学模型:
- 组合数学中的子集选择问题
- 需要满足两个条件:
- 选择恰好k个元素
- 这k个元素的和恰好为t
2. 解题思路
2.1 算法选择
最优算法:
- 使用回溯法(DFS)
- 原因:问题规模较小(n<10),回溯法的性能足够好,且实现直观
时间和空间复杂度分析:
- 时间复杂度:O(C(n,k)),其中C(n,k)是组合数
- 空间复杂度:O(k),递归栈的深度
2.2 核心数据结构
主要数据结构的选择理由:
- 使用数组存储输入的卡路里值
- 使用递归函数的参数来追踪当前状态
数据结构的具体实现方式:
- 一维数组存储卡路里值
- 递归函数参数包含:当前位置、已选数量、当前和
数据结构的操作复杂度:
- 数组访问:O(1)
- 递归调用:每层复杂度O(1)
2.3 关键算法步骤
算法的详细步骤说明:
- 读取输入参数n、t、k和卡路里数组
- 实现DFS函数,包含以下参数:
- 当前考虑的位置
- 已经选择的运动数量
- 当前卡路里和
- DFS过程中:
- 对当前位置的运动进行选择或不选择
- 记录满足条件的解的数量
每个步骤的作用和原理:
- 选择当前运动:更新已选数量和卡路里和
- 不选择当前运动:直接考虑下一个运动
- 递归终止条件:已选够k个运动或达到数组末尾
Code
def count_exercise_combinations(n: int, t: int, k: int, calories: list) -> int:
"""
计算满足条件的运动组合数量
:param n: 运动总数
:param t: 目标卡路里和
:param k: 需要选择的运动数量
:param calories: 每个运动的卡路里列表
:return: 满足条件的组合数量
"""
# 输入验证
if not (0 < n < 10 and t > 0 and 0 < k <= n):
return 0
if any(cal <= 0 for cal in calories):
return 0
def dfs(start: int, remaining_k: int, current_sum: int) -> int:
"""
深度优先搜索函数
:param start: 当前考虑的运动索引
:param remaining_k: 还需要选择的运动数量
:param current_sum: 当前已选运动的卡路里和
:return: 满足条件的组合数量
"""
# 基础情况:已经选够k个运动
if remaining_k == 0:
return 1 if current_sum == t else 0
# 如果剩余的运动不够选或者已经超出目标值,返回0
if start >= n or remaining_k > n - start or current_sum > t:
return 0
# 不选择当前运动
count = dfs(start + 1, remaining_k, current_sum)
# 选择当前运动
count += dfs(start + 1, remaining_k - 1, current_sum + calories[start])
return count
return dfs(0, k, 0)
# 测试代码
if __name__ == "__main__":
# 读取输入
n, t, k = map(int, input().split())
calories = list(map(int, input().split()))
# 输出结果
print(count_exercise_combinations(n, t, k, calories))
【华为od机试真题Python+JS+Java合集】【超值优惠】:Py/JS/Java合集
【华为od机试真题Python】:Python真题题库
【华为od机试真题JavaScript】:JavaScript真题题库
【华为od机试真题Java】:Java真题题库
【华为od机试真题C++】:C++真题题库
【华为od机试真题C语言】:C语言真题题库
【华为od面试手撕代码题库】:面试手撕代码题库
【华为od机试面试交流群:830285880】
华为OD机试:二本院校有机会吗?
有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。