目录
题目
小明有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
#include <iostream>
#include <vector>
using namespace std;
class Solution {
private:
/**
* 深度优先搜索辅助函数
* @param start 当前考虑的运动索引
* @param remainingK 还需要选择的运动数量
* @param currentSum 当前已选运动的卡路里和
* @param n 运动总数
* @param t 目标卡路里和
* @param calories 卡路里数组
* @return 满足条件的组合数量
*/
int dfs(int start, int remainingK, int currentSum,
int n, int t, const vector<int>& calories) {
// 基础情况:已经选够k个运动
if (remainingK == 0) {
return currentSum == t ? 1 : 0;
}
// 如果剩余的运动不够选或者已经超出目标值,返回0
if (start >= n || remainingK > n - start || currentSum > t) {
return 0;
}
// 不选择当前运动
int count = dfs(start + 1, remainingK, currentSum, n, t, calories);
// 选择当前运动
count += dfs(start + 1, remainingK - 1,
currentSum + calories[start], n, t, calories);
return count;
}
public:
/**
* 计算满足条件的运动组合数量
* @param n 运动总数
* @param t 目标卡路里和
* @param k 需要选择的运动数量
* @param calories 每个运动的卡路里向量
* @return 满足条件的组合数量
*/
int countExerciseCombinations(int n, int t, int k, vector<int>& calories) {
// 输入验证
if (!(0 < n && n < 10 && t > 0 && 0 < k && k <= n)) {
return 0;
}
return dfs(0, k, 0, n, t, calories);
}
};
int main() {
int n, t, k;
// 读取输入
cin >> n >> t >> k;
vector<int> calories(n);
for (int i = 0; i < n; i++) {
cin >> calories[i];
}
Solution solution;
// 输出结果
cout << solution.countExerciseCombinations(n, t, k, calories) << endl;
return 0;
}
【华为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。让他帮助你查询原因。